Merge pull request #12702 from fjricci/objc_interop

Objc interop
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c199e8..2043392 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,7 +26,7 @@
 	constraints, which require that the associated type conform to the enclosing
 	protocol. The standard library protocols have been updated to make use of
 	recursive constraints. For example, the `SubSequence` associated type of
-	follows the enclosing protocol:
+	`Sequence` follows the enclosing protocol:
 
         protocol Sequence {
           associatedtype Element
@@ -102,6 +102,8 @@
 
   If you wish to provide your own implementation of `==`/`hashValue`, you still can; a custom implementation will replace the one synthesized by the compiler.
 
+  **Add new entries to the top of this file, not here!**
+
 Swift 4.0
 ---------
 
@@ -391,8 +393,6 @@
   #define LIMITED (SMALL || TINY)   // now imported as Bool.
   ```
 
-  **Add new entries to the top of this file, not here!**
-
 Swift 3.1
 ---------
 
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
index b6244ec..1309040 100644
--- a/CODE_OWNERS.TXT
+++ b/CODE_OWNERS.TXT
@@ -4,49 +4,85 @@
 what goes in or not.
 
 The list is sorted by surname and formatted to allow easy grepping and
-beautification by scripts.  The fields are: name (N), email (E), web-address
-(W), description (D).
+beautification by scripts.  The fields are: name (N), email (E),
+GitHub account (G), description (D).
 
 N: Ben Cohen
 E: ben_cohen@apple.com
+G: airspeedswift
 D: Swift standard library
 
+N: Brian Croom
+E: bcroom@apple.com
+G: briancroom
+D: XCTest overlay
+
 N: Erik Eckstein
 E: eeckstein@apple.com
+G: eeckstein
 D: SILOptimizer
 
 N: Xi Ge
 E: xi_ge@apple.com
+G: nkcsgexi
 D: Markup, Migrator, lib/Syntax
 
 N: Doug Gregor
 E: dgregor@apple.com
+G: DougGregor
 D: AST, Basic, Parse, Sema
 
 N: Joe Groff
 E: jgroff@apple.com
+G: jckarter
 D: SIL, SILGen, everything in Swift not covered by someone else
 
 N: Argyrios Kyrzidis
 E: kyrtzidis@apple.com
-D: IDE, SourceKit, swift-ide-test
+G: akyrtzi
+D: IDE, Index, SourceKit, swift-ide-test
 
 N: Luke Larson
 E: llarson@apple.com
+G: lplarson
 D: Swift Benchmark Suite
 
 N: John McCall
 E: rjmccall@apple.com
+G: rjmccall
 D: Demangler, IRGen, Runtime
 
+N: Max Moiseev
+E: moiseev@apple.com
+G: moiseev
+D: Apple contact for non-corelibs overlays
+
+N: Tony Parker
+E: anthony.parker@apple.com
+G: parkera
+D: Foundation overlay
+
 N: Slava Pestov
 E: spestov@apple.com
+G: slavapestov
 D: Reflection, SwiftRemoteMirror
 
+N: Adrian Prantl
+E: aprantl@apple.com
+G: adrian-prantl
+D: Debug info
+
 N: Jordan Rose
 E: jordan_rose@apple.com
-D: ClangImporter, Serialization, (Objective-)C printer, Driver
+G: jrose-apple
+D: ClangImporter, Serialization, PrintAsObjC, Driver, Frontend
+
+N: Daniel Steffen
+E: dsteffen@apple.com
+G: das
+D: Dispatch overlay
 
 N: Anna Zaks
 E: ganna@apple.com
-D: SIL diagnostics passes
+G: AnnaZaks
+D: SIL diagnostics passes, sanitizers
diff --git a/README.md b/README.md
index 8c31bbe..7ef4f79 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
 
 #### macOS
 
-To build for macOS, you need [Xcode 9.1](https://developer.apple.com/xcode/downloads/).
+To build for macOS, you need [Xcode 9.2 beta 2](https://developer.apple.com/xcode/downloads/).
 The required version of Xcode changes frequently, and is often a beta release.
 Check this document or the host information on <https://ci.swift.org> for the
 current required version.
diff --git a/benchmark/single-source/CString.swift b/benchmark/single-source/CString.swift
index 9167d97..e54e675 100644
--- a/benchmark/single-source/CString.swift
+++ b/benchmark/single-source/CString.swift
@@ -31,7 +31,7 @@
 public func run_StringWithCString(_ N: Int) {
   let str = String(repeating: "x", count: 100 * (1 << 16))
   for _ in 0 ..< N {
-    str.withCString { _ in }
+    str.withCString { blackHole($0) }
   }
 }
 
diff --git a/benchmark/single-source/StringTests.swift b/benchmark/single-source/StringTests.swift
index 0ff145a..44d0e18 100644
--- a/benchmark/single-source/StringTests.swift
+++ b/benchmark/single-source/StringTests.swift
@@ -26,9 +26,7 @@
   let testString = "prefixedString"
   for _ in 0 ..< N {
     for _ in 0 ..< 100_000 {
-      if !testString.hasPrefix(prefix) {
-        CheckResults(false)
-      }
+      CheckResults(testString.hasPrefix(getString(prefix)))
     }
   }
 #endif
@@ -41,9 +39,7 @@
   let testString = "StringSuffixed"
   for _ in 0 ..< N {
     for _ in 0 ..< 100_000 {
-      if !testString.hasSuffix(suffix) {
-        CheckResults(false)
-      }
+      CheckResults(testString.hasSuffix(getString(suffix)))
     }
   }
 #endif
@@ -56,9 +52,7 @@
   let testString = "❄️prefixedString"
   for _ in 0 ..< N {
     for _ in 0 ..< 100_000 {
-      if !testString.hasPrefix(prefix) {
-        CheckResults(false)
-      }
+      CheckResults(testString.hasPrefix(getString(prefix)))
     }
   }
 #endif
@@ -71,9 +65,7 @@
   let testString = "String❄️Suffixed"
   for _ in 0 ..< N {
     for _ in 0 ..< 100_000 {
-      if !testString.hasSuffix(suffix) {
-        CheckResults(false)
-      }
+      CheckResults(testString.hasSuffix(getString(suffix)))
     }
   }
 #endif
@@ -89,9 +81,7 @@
   let str2 = str1
   for _ in 0 ..< N {
     for _ in 0 ..< 100_000 {
-      if !compareEqual(str1, str2) {
-        CheckResults(false)
-      }
+      CheckResults(compareEqual(str1, str2))
     }
   }
 }
diff --git a/benchmark/utils/TestsUtils.swift b/benchmark/utils/TestsUtils.swift
index 4d25363..42af8a2 100644
--- a/benchmark/utils/TestsUtils.swift
+++ b/benchmark/utils/TestsUtils.swift
@@ -183,10 +183,17 @@
 // Just consume the argument.
 // It's important that this function is in another module than the tests
 // which are using it.
+@inline(never)
 public func blackHole<T>(_ x: T) {
 }
 
 // Return the passed argument without letting the optimizer know that.
+@inline(never)
+public func identity<T>(_ x: T) -> T {
+  return x
+}
+
+// Return the passed argument without letting the optimizer know that.
 // It's important that this function is in another module than the tests
 // which are using it.
 @inline(never)
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 91e5cdb..5dd2ae9 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -719,7 +719,7 @@
   # On platforms that use ELF binaries we add markers for metadata sections in
   # the shared libraries using these object files.  This wouldn't be necessary
   # if the link was done by the swift binary: rdar://problem/19007002
-  if(SWIFTLIB_TARGET_LIBRARY AND
+  if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
      "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
     if("${libkind}" STREQUAL "SHARED")
       set(arch_subdir "${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}")
@@ -874,7 +874,8 @@
 
   # The section metadata objects are generated sources, and we need to tell CMake
   # not to expect to find them prior to their generation.
-  if("${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
+  if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
+     "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
     if("${libkind}" STREQUAL "SHARED")
       set_source_files_properties(${SWIFT_SECTIONS_OBJECT_BEGIN} PROPERTIES GENERATED 1)
       set_source_files_properties(${SWIFT_SECTIONS_OBJECT_END} PROPERTIES GENERATED 1)
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index a832224..5c2db0f 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -81,7 +81,9 @@
   # HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
   # into swift.  The use of this flag pollutes all targets, and we are not able
   # to remove it on a per-target basis which breaks cross-compilation.
-  string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+    string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+  endif()
 
   set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
   string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" PACKAGE_VERSION_MAJOR
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index 01ebd19..0e4b414 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -256,10 +256,15 @@
                             "-Xfrontend" "${GROUP_INFO_JSON_FILE}")
   endif()
 
-  # Force swift 3 compatibility mode for Standard Library and overlay.
-  if (SWIFTFILE_IS_STDLIB OR SWIFTFILE_IS_SDK_OVERLAY)
+  # Force swift 3 compatibility mode for Standard Library.
+  if (SWIFTFILE_IS_STDLIB)
     list(APPEND swift_flags "-swift-version" "3")
   endif()
+  
+  # Force swift 4 compatibility mode for overlays.
+  if (SWIFTFILE_IS_SDK_OVERLAY)
+    list(APPEND swift_flags "-swift-version" "4")
+  endif()
 
   if(SWIFTFILE_IS_SDK_OVERLAY)
     list(APPEND swift_flags "-autolink-force-load")
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 97ec635..f56ba09 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -317,6 +317,7 @@
   type ::= 'BO'                              // Builtin.UnknownObject
   type ::= 'Bo'                              // Builtin.NativeObject
   type ::= 'Bp'                              // Builtin.RawPointer
+  type ::= 'Bt'                              // Builtin.SILToken
   type ::= type 'Bv' NATURAL '_'             // Builtin.Vec<n>x<type>
   type ::= 'Bw'                              // Builtin.Word
   type ::= function-signature 'c'            // function type
diff --git a/docs/ABI/TypeMetadata.rst b/docs/ABI/TypeMetadata.rst
index 6fffd9d..e765d8d 100644
--- a/docs/ABI/TypeMetadata.rst
+++ b/docs/ABI/TypeMetadata.rst
@@ -121,20 +121,22 @@
 In addition to the `common metadata layout`_ fields, function metadata records
 contain the following fields:
 
-- The function flags are stored at **offset 1**, information contained by flags
-  includes 'throws' indicator (8 bits), metadata convention (8 bits)
-  and number of arguments (remaining N bits).
-- The **argument vector** begins at **offset 2** and consists of pointers to
-  metadata records of the function's arguments.
-- A reference to the **result type** metadata record is stored after the end
-  of **argument vector**. If the function has multiple returns, this references a
-  `tuple metadata`_ record.
+- The function flags are stored at **offset 1**, information contained by function
+  flags includes flags (8 bits) which _currently_ consists of 'throws' bit and
+  'parameter flags' bit, function convention (8 bits), and number of parameters (16 bits).
+- A reference to the **result type** metadata record is stored after function
+  flags. If the function has multiple returns, this references a `tuple metadata`_
+  record.
+- The **parameter type vector** follows the result type and consists of
+  NumParameters type metadata pointers corresponding to the types of the parameters.
+- The optional **parameter flags vector** begins after the end of **parameter type vector**
+  and consists of NumParameters unsigned 32-bit integer values representing flags
+  for each parameter such as inout, __shared, variadic and possibly others. This
+  vector is present only if the hasParameterFlags() function flag is set; otherwise
+  all of the parameter flags are assumed to be zero.
 
-  A pointer to each argument's metadata record will be appended separately,
-  the lowest bit being set if it is **inout**. Because of pointer alignment,
-  the lowest bit will always be free to hold this tag.
-
-  If the function takes no arguments, **argument vector** is going to be empty.
+  If the function takes no arguments, **parameter type vector** as well as
+  **parameter flags vector** are going to be empty.
 
 Protocol Metadata
 ~~~~~~~~~~~~~~~~~
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index e07f255..e037a74 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -9,7 +9,9 @@
     - [Smoke Testing](#smoke-testing)
     - [Validation Testing](#validation-testing)
     - [Linting](#linting)
+    - [Source Compatibility Testing](#source-compatibility-testing)
     - [Specific Preset Testing](#specific-preset-testing)
+    - [Testing Compiler Performance](#testing-compiler-performance)
 - [Cross Repository Testing](#cross-repository-testing)
 - [ci.swift.org bots](#ciswiftorg-bots)
 
@@ -31,6 +33,7 @@
 4. Linting
 5. Source Compatibility Testing
 6. Specific Preset Testing
+7. Testing Compiler Performance
 
 We describe each in detail below:
 
diff --git a/docs/SIL.rst b/docs/SIL.rst
index a6753b4..80e0ff8 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -582,6 +582,46 @@
     importer only imports non-native methods and types as ``throws``
     when it is possible to do this automatically.
 
+Coroutine Types
+```````````````
+
+A coroutine is a function which can suspend itself and return control to
+its caller without terminating the function.  That is, it does not need to
+obey a strict stack discipline.
+
+SIL supports two kinds of coroutine: ``@yield_many`` and ``@yield_once``.
+Either of these attributes may be written before a function type to
+indicate that it is a coroutine type.
+
+A coroutine type may declare any number of *yielded values*, which is to
+say, values which are provided to the caller at a yield point.  Yielded
+values are written in the result list of a function type, prefixed by
+the ``@yields`` attribute.  A yielded value may have a convention attribute,
+taken from the set of parameter attributes and interpreted as if the yield
+site were calling back to the calling function.
+
+Currently, a coroutine may not have normal results.
+
+Coroutine functions may be used in many of the same ways as normal
+function values.  However, they cannot be called with the standard
+``apply`` or ``try_apply`` instructions.  A non-throwing yield-once
+coroutine can be called with the ``begin_apply`` instruction.  There
+is no support yet for calling a throwing yield-once coroutine or for
+calling a yield-many coroutine of any kind.
+
+Coroutines may contain the special ``yield`` and ``unwind`` instructions.
+
+A ``@yield_many`` coroutine may yield as many times as it desires.
+A ``@yield_once`` coroutine may yield exactly once before returning,
+although it may also ``throw`` before reaching that point.
+
+This coroutine representation is well-suited to coroutines whose control
+flow is tightly integrated with their callers and which intend to pass
+information back and forth.  This matches the needs of generalized
+accessor and generator features in Swift.  It is not a particularly good
+match for ``async``/``await``-style features; a simpler representation
+would probably do fine for that.
+
 Properties of Types
 ```````````````````
 
@@ -3100,6 +3140,102 @@
 given substitution list. The arguments and return value is
 given with these generic substitutions applied.
 
+begin_apply
+```````````
+::
+
+  sil-instruction ::= 'begin_apply' '[nothrow]'? sil-value
+                        sil-apply-substitution-list?
+                        '(' (sil-value (',' sil-value)*)? ')'
+                        ':' sil-type
+
+  (%anyAddr, %float, %token) = begin_apply %0() : $@yield_once () -> (@yields @inout %Any, @yields Float)
+  // %anyAddr : $*Any
+  // %float : $Float
+  // %token is a token
+
+Transfers control to coroutine ``%0``, passing it the given arguments.
+The rules for the application generally follow the rules for ``apply``,
+except:
+
+- the callee value must have a ``yield_once`` coroutine type,
+
+- control returns to this function not when the coroutine performs a
+  ``return``, but when it performs a ``yield``, and
+
+- the instruction results are derived from the yields of the coroutine
+  instead of its normal results.
+
+The final result of a ``begin_apply`` is a "token", a special value which
+can only be used as the operand of an ``end_apply`` or ``abort_apply``
+instruction.  Before this second instruction is executed, the coroutine
+is said to be "suspended", and the token represents a reference to its
+suspended activation record.
+
+The other results of the instruction correspond to the yields in the
+coroutine type.  In general, the rules of a yield are similar to the rules
+for a parameter, interpreted as if the coroutine caller (the one
+executing the ``begin_apply``) were being "called" by the ``yield``:
+
+- If a yield has an indirect convention, the corresponding result will
+  have an address type; otherwise it has an object type.  For example,
+  a result corresponding to an ``@in Any`` yield will have type ``$Any``.
+
+- The convention attributes are the same as the parameter convention
+  attributes, interpreted as if the ``yield`` were the "call" and the
+  ``begin_apply`` marked the entry to the "callee".  For example,
+  an ``@in Any`` yield transferrs ownership of the ``Any`` value
+  reference from the coroutine to the caller, which must destroy
+  or move the value from that position before ending or aborting the
+  coroutine.
+
+A ``begin_apply`` must be uniquely either ended or aborted before
+exiting the function or looping to an earlier portion of the function.
+
+When throwing coroutines are supported, there will need to be a
+``try_begin_apply`` instruction.
+
+abort_apply
+```````````
+::
+
+  sil-instruction ::= 'abort_apply' sil-value
+
+  abort_apply %token
+
+Aborts the given coroutine activation, which is currently suspended at
+a ``yield`` instruction.  Transfers control to the coroutine and takes
+the ``unwind`` path from the ``yield``.  Control is transferred back
+when the coroutine reaches an ``unwind`` instruction.
+
+The operand must always be the token result of a ``begin_apply``
+instruction, which is why it need not specify a type.
+
+Throwing coroutines will not require a new instruction for aborting
+a coroutine; a coroutine is not allowed to throw when it is being aborted.
+
+end_apply
+`````````
+::
+
+  sil-instruction ::= 'end_apply' sil-value
+
+  end_apply %token
+
+Ends the given coroutine activation, which is currently suspended at
+a ``yield`` instruction.  Transfers control to the coroutine and takes
+the ``resume`` path from the ``yield``.  Control is transferred back
+when the coroutine reaches a ``return`` instruction.
+
+The operand must always be the token result of a ``begin_apply``
+instruction, which is why it need not specify a type.
+
+``end_apply`` currently has no instruction results.  If coroutines were
+allowed to have normal results, they would be producted by ``end_apply``.
+
+When throwing coroutines are supported, there will need to be a
+``try_end_apply`` instruction.
+
 partial_apply
 `````````````
 ::
@@ -4698,6 +4834,10 @@
 resumes at the normal destination, and the value of the basic block argument
 will be the operand of this ``return`` instruction.
 
+If the current function is a ``yield_once`` coroutine, there must not be
+a path from the entry block to a ``return`` which does not pass through
+a ``yield`` instruction. This rule does not apply in the ``raw`` SIL stage.
+
 ``return`` does not retain or release its operand or any other values.
 
 A function must not contain more than one ``return`` instruction.
@@ -4713,7 +4853,7 @@
 
 Exits the current function and returns control to the calling
 function. The current function must have an error result, and so the
-function must have been invoked with a ``try_apply` instruction.
+function must have been invoked with a ``try_apply`` instruction.
 Control will resume in the error destination of that instruction, and
 the basic block argument will be the operand of the ``throw``.
 
@@ -4721,6 +4861,50 @@
 
 A function must not contain more than one ``throw`` instruction.
 
+yield
+`````
+::
+
+  sil-terminator ::= 'yield' sil-yield-values
+                       ',' 'resume' sil-identifier
+                       ',' 'unwind' sil-identifier
+  sil-yield-values ::= sil-operand
+  sil-yield-values ::= '(' (sil-operand (',' sil-operand)*)? ')'
+
+Temporarily suspends the current function and provides the given
+values to the calling function. The current function must be a coroutine,
+and the yield values must match the yield types of the coroutine.
+If the calling function resumes the coroutine normally, control passes to
+the ``resume`` destination. If the calling function aborts the coroutine,
+control passes to the ``unwind`` destination.
+
+The ``resume`` and ``unwind`` destination blocks must be uniquely
+referenced by the ``yield`` instruction.  This prevents them from becoming
+critical edges.
+
+In a ``yield_once`` coroutine, there must not be a control flow path leading
+from the ``resume`` edge to another ``yield`` instruction in this function.
+This rule does not apply in the ``raw`` SIL stage.
+
+There must not be a control flow path leading from the ``unwind`` edge to
+a ``return`` instruction, to a ``throw`` instruction, or to any block
+reachable from the entry block via a path that does not pass through
+an ``unwind`` edge. That is, the blocks reachable from ``unwind`` edges
+must jointly form a disjoint subfunction of the coroutine.
+
+unwind
+``````
+::
+
+  sil-terminator ::= 'unwind'
+
+Exits the current function and returns control to the calling function,
+completing an unwind from a ``yield``. The current function must be a
+coroutine.
+
+``unwind`` is only permitted in blocks reachable from the ``unwind`` edges
+of ``yield`` instructions.
+
 br
 ``
 ::
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0259ba7..69027e2 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -549,11 +549,15 @@
 /// Flags in a function type metadata record.
 template <typename int_type>
 class TargetFunctionTypeFlags {
+  // If we were ever to run out of space for function flags (8 bits)
+  // one of the flag bits could be used to identify that the rest of
+  // the flags is going to be stored somewhere else in the metadata.
   enum : int_type {
-    NumArgumentsMask = 0x00FFFFFFU,
-    ConventionMask   = 0x0F000000U,
-    ConventionShift  = 24U,
-    ThrowsMask       = 0x10000000U,
+    NumParametersMask = 0x0000FFFFU,
+    ConventionMask    = 0x00FF0000U,
+    ConventionShift   = 16U,
+    ThrowsMask        = 0x01000000U,
+    ParamFlagsMask    = 0x02000000U,
   };
   int_type Data;
   
@@ -561,8 +565,9 @@
 public:
   constexpr TargetFunctionTypeFlags() : Data(0) {}
 
-  constexpr TargetFunctionTypeFlags withNumArguments(unsigned numArguments) const {
-    return TargetFunctionTypeFlags((Data & ~NumArgumentsMask) | numArguments);
+  constexpr TargetFunctionTypeFlags
+  withNumParameters(unsigned numParams) const {
+    return TargetFunctionTypeFlags((Data & ~NumParametersMask) | numParams);
   }
   
   constexpr TargetFunctionTypeFlags<int_type>
@@ -576,11 +581,15 @@
     return TargetFunctionTypeFlags<int_type>((Data & ~ThrowsMask) |
                                              (throws ? ThrowsMask : 0));
   }
-  
-  unsigned getNumArguments() const {
-    return Data & NumArgumentsMask;
+
+  constexpr TargetFunctionTypeFlags<int_type>
+  withParameterFlags(bool hasFlags) const {
+    return TargetFunctionTypeFlags<int_type>((Data & ~ParamFlagsMask) |
+                                             (hasFlags ? ParamFlagsMask : 0));
   }
-  
+
+  unsigned getNumParameters() const { return Data & NumParametersMask; }
+
   FunctionMetadataConvention getConvention() const {
     return FunctionMetadataConvention((Data&ConventionMask) >> ConventionShift);
   }
@@ -588,7 +597,9 @@
   bool throws() const {
     return bool(Data & ThrowsMask);
   }
-  
+
+  bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }
+
   int_type getIntValue() const {
     return Data;
   }
@@ -606,6 +617,56 @@
 };
 using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;
 
+template <typename int_type>
+class TargetParameterTypeFlags {
+  enum : int_type {
+    InOutMask    = 1 << 0,
+    SharedMask   = 1 << 1,
+    VariadicMask = 1 << 2,
+  };
+  int_type Data;
+
+  constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}
+
+public:
+  constexpr TargetParameterTypeFlags() : Data(0) {}
+
+  constexpr TargetParameterTypeFlags<int_type> withInOut(bool isInOut) const {
+    return TargetParameterTypeFlags<int_type>((Data & ~InOutMask) |
+                                              (isInOut ? InOutMask : 0));
+  }
+
+  constexpr TargetParameterTypeFlags<int_type> withShared(bool isShared) const {
+    return TargetParameterTypeFlags<int_type>((Data & ~SharedMask) |
+                                              (isShared ? SharedMask : 0));
+  }
+
+  constexpr TargetParameterTypeFlags<int_type>
+  withVariadic(bool isVariadic) const {
+    return TargetParameterTypeFlags<int_type>((Data & ~VariadicMask) |
+                                              (isVariadic ? VariadicMask : 0));
+  }
+
+  bool isNone() const { return Data == 0; }
+  bool isInOut() const { return Data & InOutMask; }
+  bool isShared() const { return Data & SharedMask; }
+  bool isVariadic() const { return Data & VariadicMask; }
+
+  int_type getIntValue() const { return Data; }
+
+  static TargetParameterTypeFlags<int_type> fromIntValue(int_type Data) {
+    return TargetParameterTypeFlags(Data);
+  }
+
+  bool operator==(TargetParameterTypeFlags<int_type> other) const {
+    return Data == other.Data;
+  }
+  bool operator!=(TargetParameterTypeFlags<int_type> other) const {
+    return Data != other.Data;
+  }
+};
+using ParameterFlags = TargetParameterTypeFlags<uint32_t>;
+
 /// Field types and flags as represented in a nominal type's field/case type
 /// vector.
 class FieldType {
diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index 3d52776..0ee1eb5 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -573,6 +573,7 @@
   const CanType TheUnknownObjectType;     /// Builtin.UnknownObject
   const CanType TheRawPointerType;        /// Builtin.RawPointer
   const CanType TheUnsafeValueBufferType; /// Builtin.UnsafeValueBuffer
+  const CanType TheSILTokenType;          /// Builtin.SILToken
   
   const CanType TheIEEE32Type;            /// 32-bit IEEE floating point
   const CanType TheIEEE64Type;            /// 64-bit IEEE floating point
@@ -884,15 +885,6 @@
                                        GenericSignatureBuilder *builder,
                                        GenericSignature *sig);
 
-  /// Retrieve the inherited name set for the given class.
-  const InheritedNameSet *getAllPropertyNames(ClassDecl *classDecl,
-                                              bool forInstance);
-
-  /// Retrieve the inherited name set for the given Objective-C class.
-  const InheritedNameSet *getAllPropertyNames(
-                            clang::ObjCInterfaceDecl *classDecl,
-                            bool forInstance);
-
   /// Retrieve a generic signature with a single unconstrained type parameter,
   /// like `<T>`.
   CanGenericSignature getSingleGenericParameterSignature() const;
diff --git a/include/swift/AST/ASTMangler.h b/include/swift/AST/ASTMangler.h
index 0c931d0..8a99f64 100644
--- a/include/swift/AST/ASTMangler.h
+++ b/include/swift/AST/ASTMangler.h
@@ -46,6 +46,7 @@
   enum class SymbolKind {
     Default,
     DynamicThunk,
+    SwiftDispatchThunk,
     SwiftAsObjCThunk,
     ObjCAsSwiftThunk,
     DirectMethodReferenceThunk,
diff --git a/include/swift/AST/ASTNode.h b/include/swift/AST/ASTNode.h
index 078b5bc..5332fa7 100644
--- a/include/swift/AST/ASTNode.h
+++ b/include/swift/AST/ASTNode.h
@@ -18,7 +18,6 @@
 #define SWIFT_AST_AST_NODE_H
 
 #include "llvm/ADT/PointerUnion.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/AST/TypeAlignments.h"
 
 namespace swift {
@@ -48,9 +47,6 @@
     void walk(ASTWalker &Walker);
     void walk(ASTWalker &&walker) { walk(walker); }
 
-    void walk(SourceEntityWalker &Walker);
-    void walk(SourceEntityWalker &&walker) { walk(walker); }
-
     /// \brief get the underlying entity as a decl context if it is one,
     /// otherwise, return nullptr;
     DeclContext *getAsDeclContext() const;
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index c7629da..26e8b05 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -60,6 +60,9 @@
 TYPE_ATTR(objc_metatype)
 TYPE_ATTR(opened)
 TYPE_ATTR(pseudogeneric)
+TYPE_ATTR(yields)
+TYPE_ATTR(yield_once)
+TYPE_ATTR(yield_many)
 
 // SIL metatype attributes.
 TYPE_ATTR(thin)
@@ -296,6 +299,10 @@
                  ImplicitlyUnwrappedOptional,
                  OnFunc | OnVar | OnSubscript | OnConstructor | RejectByParser, 72)
 
+DECL_ATTR(_optimize, Optimize,
+          OnFunc | OnConstructor | OnDestructor | OnSubscript | OnVar |
+          UserInaccessible, 73)
+
 #undef TYPE_ATTR
 #undef DECL_ATTR_ALIAS
 #undef SIMPLE_DECL_ATTR
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index 925aa7d..2db33d7 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -21,6 +21,7 @@
 #include "swift/Basic/UUID.h"
 #include "swift/Basic/STLExtras.h"
 #include "swift/Basic/Range.h"
+#include "swift/Basic/OptimizationMode.h"
 #include "swift/Basic/Version.h"
 #include "swift/AST/Identifier.h"
 #include "swift/AST/AttrKind.h"
@@ -925,6 +926,23 @@
   }
 };
 
+/// Represents the optimize attribute.
+class OptimizeAttr : public DeclAttribute {
+  OptimizationMode Mode;
+public:
+  OptimizeAttr(SourceLoc atLoc, SourceRange range, OptimizationMode mode)
+    : DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false),
+      Mode(mode) {}
+
+  OptimizeAttr(OptimizationMode mode)
+    : OptimizeAttr(SourceLoc(), SourceRange(), mode) {}
+
+  OptimizationMode getMode() const { return Mode; }
+  static bool classof(const DeclAttribute *DA) {
+    return DA->getKind() == DAK_Optimize;
+  }
+};
+
 /// Represents the side effects attribute.
 class EffectsAttr : public DeclAttribute {
   EffectsKind Kind;
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c89e436..5be9bbc 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -458,8 +458,12 @@
 
     /// Whether there is are lazily-loaded conformances for this nominal type.
     unsigned HasLazyConformances : 1;
+
+    /// Whether we have already validated all members of the type that
+    /// affect layout.
+    unsigned HasValidatedLayout : 1;
   };
-  enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 3 };
+  enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 4 };
   static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");
 
   class ProtocolDeclBitfields {
@@ -771,6 +775,9 @@
   /// Returns the source range of the entire declaration.
   SourceRange getSourceRange() const;
 
+  /// Returns the source range of the declaration including its attributes.
+  SourceRange getSourceRangeIncludingAttrs() const;
+
   SourceLoc TrailingSemiLoc;
 
   LLVM_ATTRIBUTE_DEPRECATED(
@@ -2218,6 +2225,10 @@
   getFormalAccessScope(const DeclContext *useDC = nullptr,
                        bool respectVersionedAttr = false) const;
 
+
+  /// Copy the formal access level and @_versioned attribute from source.
+  void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source);
+
   /// Returns the access level that actually controls how a declaration should
   /// be emitted and may be used.
   ///
@@ -2814,6 +2825,7 @@
     NominalTypeDeclBits.AddedImplicitInitializers = false;
     ExtensionGeneration = 0;
     NominalTypeDeclBits.HasLazyConformances = false;
+    NominalTypeDeclBits.HasValidatedLayout = false;
   }
 
   friend class ProtocolType;
@@ -2856,11 +2868,23 @@
     return NominalTypeDeclBits.AddedImplicitInitializers;
   }
 
-  /// Note that we have attempted to
+  /// Note that we have attempted to add implicit initializers.
   void setAddedImplicitInitializers() {
     NominalTypeDeclBits.AddedImplicitInitializers = true;
   }
-              
+
+  /// Determine whether we have already validated any members
+  /// which affect layout.
+  bool hasValidatedLayout() const {
+    return NominalTypeDeclBits.HasValidatedLayout;
+  }
+
+  /// Note that we have attempted to validate any members
+  /// which affect layout.
+  void setHasValidatedLayout() {
+    NominalTypeDeclBits.HasValidatedLayout = true;
+  }
+
   /// Compute the type of this nominal type.
   void computeType();
 
@@ -3382,7 +3406,7 @@
 
   /// Synthesize implicit, trivial destructor, add it to this ClassDecl
   /// and return it.
-  DestructorDecl *addImplicitDestructor();
+  void addImplicitDestructor();
 
   /// Determine whether this class inherits the convenience initializers
   /// from its superclass.
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 52dc174..ffe5f92 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -385,6 +385,10 @@
     return false;
   }
 
+  /// Compute a context C such that C is a parent context of A and B.
+  /// If no such context exists, return \c nullptr.
+  static DeclContext *getCommonParentContext(DeclContext *A, DeclContext *B);
+
   /// Returns the module context that contains this context.
   ModuleDecl *getParentModule() const;
 
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 41c6cf4..570fc54 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1365,10 +1365,10 @@
 ERROR(opened_attribute_expected_rparen,none,
       "expected ')' after id value for 'opened' attribute", ())
 
-// inline
-ERROR(inline_attribute_expect_option,none,
-      "expected '%0' option such as 'never'", (StringRef))
-ERROR(inline_attribute_unknown_option,none,
+// inline, optimize
+ERROR(optimization_attribute_expect_option,none,
+      "expected '%0' option such as '%1'", (StringRef, StringRef))
+ERROR(optimization_attribute_unknown_option,none,
       "unknown option '%0' for attribute '%1'", (StringRef, StringRef))
 
 // effects
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index a832920..fa41dab 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -474,6 +474,9 @@
       "key path cannot reference tuple elements", ())
 ERROR(expr_keypath_subscript_index_not_hashable, none,
       "subscript index of type %0 in a key path must be Hashable", (Type))
+ERROR(expr_smart_keypath_application_type_mismatch,none,
+      "key path of type %0 cannot be applied to a base of type %1",
+      (Type, Type))
 
 // Selector expressions.
 ERROR(expr_selector_no_objc_runtime,none,
@@ -1024,8 +1027,6 @@
 ERROR(static_functions_not_mutating,none,
       "static functions must not be declared mutating", ())
 
-ERROR(transparent_stored_property,none,
-      "@_transparent cannot be applied to stored properties", ())
 ERROR(transparent_in_protocols_not_supported,none,
       "@_transparent is not supported on declarations within protocols", ())
 ERROR(transparent_in_classes_not_supported,none,
@@ -3183,6 +3184,8 @@
       "SIL function types cannot have labeled inputs", ())
 ERROR(sil_function_output_label,PointsToFirstBadToken,
       "SIL function types cannot have labeled results", ())
+ERROR(sil_non_coro_yields,PointsToFirstBadToken,
+      "non-coroutine SIL function types cannot have @yield results", ())
 ERROR(sil_function_repeat_convention,PointsToFirstBadToken,
       "repeated %select{parameter|result|callee}0 convention attribute",
       (unsigned))
@@ -3703,8 +3706,8 @@
       "'%select{@_transparent|@inline(__always)|@_inlineable|%error}1' and must "
       "delegate to another initializer", (Type, unsigned))
 
-ERROR(inlineable_stored_property,
-      none, "'@_inlineable' attribute cannot be applied to stored properties", ())
+ERROR(attribute_invalid_on_stored_property,
+      none, "@%0 cannot be applied to stored properties", (StringRef))
 
 ERROR(inlineable_dynamic_not_supported,
       none, "'@_inlineable' attribute cannot be applied to 'dynamic' declarations", ())
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 9e8b509..35f9411 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -802,6 +802,16 @@
   /// Determine whether the two given types are in the same equivalence class.
   bool areInSameEquivalenceClass(Type type1, Type type2);
 
+  /// Verify the correctness of the given generic signature.
+  ///
+  /// This routine will test that the given generic signature is both minimal
+  /// and canonical, emitting errors if it is not.
+  static void verifyGenericSignature(ASTContext &context,
+                                     GenericSignature *sig);
+
+  /// Verify all of the generic sigantures in the given module.
+  static void verifyGenericSignaturesInModule(ModuleDecl *module);
+
   /// \brief Dump all of the requirements, both specified and inferred.
   LLVM_ATTRIBUTE_DEPRECATED(
       void dump(),
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index a72fbc5..349f769 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -21,6 +21,7 @@
 #include "swift/AST/LinkLibrary.h"
 #include "swift/Basic/Sanitizers.h"
 #include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
 // FIXME: This include is just for llvm::SanitizerCoverageOptions. We should
 // split the header upstream so we don't include so much.
 #include "llvm/Transforms/Instrumentation.h"
@@ -94,11 +95,7 @@
   /// well-formed?
   unsigned Verify : 1;
 
-  /// Whether or not to run optimization passes.
-  unsigned Optimize : 1;
-
-  /// Whether or not to optimize for code size.
-  unsigned OptimizeForSize : 1;
+  OptimizationMode OptMode;
 
   /// Which sanitizer is turned on.
   OptionSet<SanitizerKind> Sanitizers;
@@ -179,7 +176,7 @@
 
   IRGenOptions()
       : DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssembly),
-        Verify(true), Optimize(false), OptimizeForSize(false),
+        Verify(true), OptMode(OptimizationMode::NotSet),
         Sanitizers(OptionSet<SanitizerKind>()),
         DebugInfoKind(IRGenDebugInfoKind::None), UseJIT(false),
         DisableLLVMOptzns(false), DisableLLVMARCOpts(false),
@@ -202,9 +199,7 @@
   // Get a hash of all options which influence the llvm compilation but are not
   // reflected in the llvm module itself.
   unsigned getLLVMCodeGenOptionsHash() {
-    unsigned Hash = 0;
-    Hash = (Hash << 1) | Optimize;
-    Hash = (Hash << 1) | OptimizeForSize;
+    unsigned Hash = (unsigned)OptMode;
     Hash = (Hash << 1) | DisableLLVMOptzns;
     Hash = (Hash << 1) | DisableLLVMARCOpts;
     return Hash;
@@ -222,6 +217,14 @@
     }
   }
 
+  bool shouldOptimize() const {
+    return OptMode > OptimizationMode::NoOptimization;
+  }
+
+  bool optimizeForSize() const {
+    return OptMode == OptimizationMode::ForSize;
+  }
+
   /// Return a hash code of any components from these options that should
   /// contribute to a Swift Bridging PCH hash.
   llvm::hash_code getPCHHashComponents() const {
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 377b7e2..4e99b99 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -1173,6 +1173,15 @@
 
   virtual bool isSystemModule() const { return false; }
 
+  /// Retrieve the set of generic signatures stored within this module.
+  ///
+  /// \returns \c true if this module file supports retrieving all of the
+  /// generic signatures, \c false otherwise.
+  virtual bool getAllGenericSignatures(
+                 SmallVectorImpl<GenericSignature*> &genericSignatures) {
+    return false;
+  }
+
   static bool classof(const FileUnit *file) {
     return file->getKind() == FileUnitKind::SerializedAST ||
            file->getKind() == FileUnitKind::ClangModule;
diff --git a/include/swift/AST/PrettyStackTrace.h b/include/swift/AST/PrettyStackTrace.h
index 96894b1..9715dd32 100644
--- a/include/swift/AST/PrettyStackTrace.h
+++ b/include/swift/AST/PrettyStackTrace.h
@@ -26,6 +26,7 @@
   class ASTContext;
   class Decl;
   class Expr;
+  class GenericSignature;
   class Pattern;
   class Stmt;
   class TypeRepr;
@@ -129,6 +130,24 @@
   virtual void print(llvm::raw_ostream &OS) const;
 };
 
+class PrettyStackTraceGenericSignature : public llvm::PrettyStackTraceEntry {
+  const char *Action;
+  GenericSignature *GenericSig;
+  Optional<unsigned> Requirement;
+
+public:
+  PrettyStackTraceGenericSignature(const char *action,
+                                   GenericSignature *genericSig,
+                                   Optional<unsigned> requirement = None)
+    : Action(action), GenericSig(genericSig), Requirement(requirement) { }
+
+  void setRequirement(Optional<unsigned> requirement) {
+    Requirement = requirement;
+  }
+
+  void print(llvm::raw_ostream &out) const override;
+};
+
 } // end namespace swift
 
 #endif
diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h
index 3272e45..b434510 100644
--- a/include/swift/AST/PrintOptions.h
+++ b/include/swift/AST/PrintOptions.h
@@ -386,6 +386,7 @@
     result.PrintImplicitAttrs = false;
     result.ExcludeAttrList.push_back(DAK_Exported);
     result.ExcludeAttrList.push_back(DAK_Inline);
+    result.ExcludeAttrList.push_back(DAK_Optimize);
     result.ExcludeAttrList.push_back(DAK_Rethrows);
     result.PrintOverrideKeyword = false;
     result.AccessFilter = AccessLevel::Public;
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 1ae9e1f..9193c00 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -251,6 +251,13 @@
   /// interface type.
   GenericSignature *getGenericSignature() const;
 
+  /// Get the substitutions associated with this conformance.
+  SubstitutionMap getSubstitutions(ModuleDecl *M) const;
+
+  /// Determine whether the witness table access function for this conformance
+  /// needs to be passed information when called, or if it stands alone.
+  bool witnessTableAccessorRequiresArguments() const;
+
   /// Get the underlying normal conformance.
   const NormalProtocolConformance *getRootNormalConformance() const;
 
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index bbd37b9..0c51835 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -20,6 +20,7 @@
 
 #include "swift/Basic/Sanitizers.h"
 #include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringRef.h"
 #include <string>
@@ -52,16 +53,6 @@
     LinkAll
   };
 
-  /// Representation of optimization modes.
-  enum class SILOptMode: unsigned {
-    NotSet,
-    None,
-    Debug,
-    Optimize,
-    OptimizeForSize,
-    OptimizeUnchecked
-  };
-
   /// Controls how to perform SIL linking.
   LinkingMode LinkMode = LinkNormal;
 
@@ -91,7 +82,7 @@
   bool EmitVerboseSIL = false;
 
   /// Optimization mode being used.
-  SILOptMode Optimization = SILOptMode::NotSet;
+  OptimizationMode OptMode = OptimizationMode::NotSet;
 
   enum AssertConfiguration: unsigned {
     // Used by standard library code to distinguish between a debug and release
@@ -167,6 +158,10 @@
   llvm::hash_code getPCHHashComponents() const {
     return llvm::hash_value(0);
   }
+
+  bool shouldOptimize() const {
+    return OptMode > OptimizationMode::NoOptimization;
+  }
 };
 
 } // end namespace swift
diff --git a/include/swift/AST/TypeMatcher.h b/include/swift/AST/TypeMatcher.h
index c3a9c3b..7f37714 100644
--- a/include/swift/AST/TypeMatcher.h
+++ b/include/swift/AST/TypeMatcher.h
@@ -109,6 +109,7 @@
     TRIVIAL_CASE(BuiltinUnknownObjectType)
     TRIVIAL_CASE(BuiltinUnsafeValueBufferType)
     TRIVIAL_CASE(BuiltinVectorType)
+    TRIVIAL_CASE(SILTokenType)
 
     bool visitTupleType(CanTupleType firstTuple, Type secondType,
                         Type sugaredFirstType) {
diff --git a/include/swift/AST/TypeNodes.def b/include/swift/AST/TypeNodes.def
index ccfdbce..2821074 100644
--- a/include/swift/AST/TypeNodes.def
+++ b/include/swift/AST/TypeNodes.def
@@ -126,6 +126,7 @@
 ARTIFICIAL_TYPE(SILFunction, Type)
 ARTIFICIAL_TYPE(SILBlockStorage, Type)
 ARTIFICIAL_TYPE(SILBox, Type)
+ARTIFICIAL_TYPE(SILToken, Type)
 ABSTRACT_SUGARED_TYPE(SyntaxSugar, Type)
   SUGARED_TYPE(ArraySlice, SyntaxSugarType)
   SUGARED_TYPE(Optional, SyntaxSugarType)
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 10ca863..fe4a1e2 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -319,8 +319,9 @@
     unsigned ExtInfo : 16;
     unsigned CalleeConvention : 3;
     unsigned HasErrorResult : 1;
+    unsigned CoroutineKind : 2;
   };
-  enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16+5 };
+  enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16 + 6 };
   static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
 
   struct AnyMetatypeTypeBitfields {
@@ -3175,6 +3176,42 @@
     return !(*this == rhs);
   }
 };
+
+using YieldConvention = ParameterConvention;
+
+/// The type and convention of a value yielded from a yield-once or
+/// yield-many coroutine.
+class SILYieldInfo : public SILParameterInfo {
+public:
+  SILYieldInfo() {}
+  SILYieldInfo(CanType type, YieldConvention conv)
+    : SILParameterInfo(type, conv) {
+  }
+
+  SILYieldInfo getWithType(CanType type) const {
+    return SILYieldInfo(type, getConvention());
+  }
+
+  template<typename F>
+  SILYieldInfo map(const F &fn) const {
+    return getWithType(fn(getType()));
+  }
+};
+
+/// SILCoroutineKind - What kind of coroutine is this SILFunction?
+enum class SILCoroutineKind : uint8_t {
+  /// This function is not a coroutine.  It may have arbitrary normal
+  /// results and may not have yield results.
+  None,
+
+  /// This function is a yield-once coroutine (used by e.g. accessors).
+  /// It must not have normal results and may have arbitrary yield results.
+  YieldOnce,
+
+  /// This function is a yield-many coroutine (used by e.g. generators).
+  /// It must not have normal results and may have arbitrary yield results.
+  YieldMany,
+};
   
 class SILFunctionType;
 typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
@@ -3334,16 +3371,20 @@
 
 private:
   unsigned NumParameters;
-  unsigned NumResults : 16;               // Not including the ErrorResult.
-  unsigned NumIndirectFormalResults : 16; // Subset of NumResults.
+
+  // These are *normal* results if this is not a coroutine and *yield* results
+  // otherwise.
+  unsigned NumAnyResults : 16;         // Not including the ErrorResult.
+  unsigned NumAnyIndirectFormalResults : 16; // Subset of NumAnyResults.
 
   // The layout of a SILFunctionType in memory is:
   //   SILFunctionType
   //   SILParameterInfo[NumParameters]
-  //   SILResultInfo[NumResults]
-  //   SILResultInfo?                 // if hasErrorResult()
-  //   CanType?                       // if NumResults > 1, formal result cache
-  //   CanType?                       // if NumResults > 1, all result cache
+  //   SILResultInfo[isCoroutine() ? 0 : NumAnyResults]
+  //   SILYieldInfo[isCoroutine() ? NumAnyResults : 0]
+  //   SILResultInfo?    // if hasErrorResult()
+  //   CanType?          // if !isCoro && NumAnyResults > 1, formal result cache
+  //   CanType?          // if !isCoro && NumAnyResults > 1, all result cache
 
   CanGenericSignature GenericSig;
   Optional<ProtocolConformanceRef> WitnessMethodConformance;
@@ -3354,48 +3395,74 @@
 
   MutableArrayRef<SILResultInfo> getMutableResults() {
     auto *ptr = reinterpret_cast<SILResultInfo *>(getMutableParameters().end());
-    return MutableArrayRef<SILResultInfo>(ptr, getNumResults());
+    return {ptr, getNumResults()};
   }
 
-  SILResultInfo *getEndOfNormalResults() { return getMutableResults().end(); }
+  MutableArrayRef<SILYieldInfo> getMutableYields() {
+    auto *ptr = reinterpret_cast<SILYieldInfo *>(getMutableParameters().end());
+    return {ptr, getNumYields()};
+  }
+
+  /// Return a pointer past the end of the formal results, whether they
+  /// are yield-results or normal results.
+  void *getEndOfFormalResults() {
+    return isCoroutine() ? static_cast<void*>(getMutableYields().end())
+                         : static_cast<void*>(getMutableResults().end());
+  }
 
   SILResultInfo &getMutableErrorResult() {
     assert(hasErrorResult());
-    return *getEndOfNormalResults();
+    return *reinterpret_cast<SILResultInfo*>(getEndOfFormalResults());
   }
 
-  bool hasResultCache() const { return NumResults > 1; }
+  /// Return a pointer past the end of all of the results, including the
+  /// error result if one is present.
+  void *getEndOfAllResults() {
+    void *end = getEndOfFormalResults();
+    if (hasErrorResult())
+      end = reinterpret_cast<char*>(end) + sizeof(SILResultInfo);
+    return end;
+  }
+
+  /// Do we have slots for caches of the normal-result tuple type?
+  bool hasResultCache() const {
+    return NumAnyResults > 1 && !isCoroutine();
+  }
 
   CanType &getMutableFormalResultsCache() const {
     assert(hasResultCache());
-    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
-                + size_t(hasErrorResult());
+    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
     return *reinterpret_cast<CanType*>(ptr);
   }
 
   CanType &getMutableAllResultsCache() const {
     assert(hasResultCache());
-    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
-                + size_t(hasErrorResult());
+    auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
     return *(reinterpret_cast<CanType *>(ptr) + 1);
   }
 
-  SILFunctionType(
-      GenericSignature *genericSig, ExtInfo ext,
-      ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
-      ArrayRef<SILResultInfo> normalResults,
-      Optional<SILResultInfo> errorResult, const ASTContext &ctx,
-      RecursiveTypeProperties properties,
-      Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+  SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+                  SILCoroutineKind coroutineKind,
+                  ParameterConvention calleeConvention,
+                  ArrayRef<SILParameterInfo> params,
+                  ArrayRef<SILYieldInfo> yieldResults,
+                  ArrayRef<SILResultInfo> normalResults,
+                  Optional<SILResultInfo> errorResult,
+                  const ASTContext &ctx,
+                  RecursiveTypeProperties properties,
+                  Optional<ProtocolConformanceRef> witnessMethodConformance);
 
 public:
-  static CanSILFunctionType
-  get(GenericSignature *genericSig, ExtInfo ext,
-      ParameterConvention calleeConvention,
-      ArrayRef<SILParameterInfo> interfaceParams,
-      ArrayRef<SILResultInfo> interfaceResults,
-      Optional<SILResultInfo> interfaceErrorResult, const ASTContext &ctx,
-      Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+  static CanSILFunctionType get(GenericSignature *genericSig,
+                                ExtInfo ext,
+                                SILCoroutineKind coroutineKind,
+                                ParameterConvention calleeConvention,
+                                ArrayRef<SILParameterInfo> interfaceParams,
+                                ArrayRef<SILYieldInfo> interfaceYields,
+                                ArrayRef<SILResultInfo> interfaceResults,
+                                Optional<SILResultInfo> interfaceErrorResult,
+                                const ASTContext &ctx,
+              Optional<ProtocolConformanceRef> witnessMethodConformance = None);
 
   /// Given that this function type uses a C-language convention, return its
   /// formal semantic result type.
@@ -3423,12 +3490,26 @@
     return getCalleeConvention() == ParameterConvention::Direct_Guaranteed;
   }
 
+  /// Is this some kind of coroutine?
+  bool isCoroutine() const {
+    return getCoroutineKind() != SILCoroutineKind::None;
+  }
+  SILCoroutineKind getCoroutineKind() const {
+    return SILCoroutineKind(SILFunctionTypeBits.CoroutineKind);
+  }
+
+  /// Return the array of all the yields.
+  ArrayRef<SILYieldInfo> getYields() const {
+    return const_cast<SILFunctionType *>(this)->getMutableYields();
+  }
+  unsigned getNumYields() const { return isCoroutine() ? NumAnyResults : 0; }
+
   /// Return the array of all result information. This may contain inter-mingled
   /// direct and indirect results.
   ArrayRef<SILResultInfo> getResults() const {
     return const_cast<SILFunctionType *>(this)->getMutableResults();
   }
-  unsigned getNumResults() const { return NumResults; }
+  unsigned getNumResults() const { return isCoroutine() ? 0 : NumAnyResults; }
 
   /// Given that this function type has exactly one result, return it.
   /// This is a common situation when working with a function with a known
@@ -3458,14 +3539,14 @@
   // indirect property, not the SIL indirect property, should be consulted to
   // determine whether function reabstraction is necessary.
   unsigned getNumIndirectFormalResults() const {
-    return NumIndirectFormalResults;
+    return isCoroutine() ? 0 : NumAnyIndirectFormalResults;
   }
   /// Does this function have any formally indirect results?
   bool hasIndirectFormalResults() const {
     return getNumIndirectFormalResults() != 0;
   }
   unsigned getNumDirectFormalResults() const {
-    return NumResults - NumIndirectFormalResults;
+    return isCoroutine() ? 0 : NumAnyResults - NumAnyIndirectFormalResults;
   }
 
   struct IndirectFormalResultFilter {
@@ -3607,15 +3688,18 @@
                                       LookupConformanceFn conformances);
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getGenericSignature(), getExtInfo(), getCalleeConvention(),
-            getParameters(), getResults(), getOptionalErrorResult());
+    Profile(ID, getGenericSignature(), getExtInfo(), getCoroutineKind(),
+            getCalleeConvention(), getParameters(), getYields(),
+            getResults(), getOptionalErrorResult());
   }
   static void Profile(llvm::FoldingSetNodeID &ID,
                       GenericSignature *genericSig,
                       ExtInfo info,
+                      SILCoroutineKind coroutineKind,
                       ParameterConvention calleeConvention,
                       ArrayRef<SILParameterInfo> params,
-                      ArrayRef<SILResultInfo> result,
+                      ArrayRef<SILYieldInfo> yields,
+                      ArrayRef<SILResultInfo> results,
                       Optional<SILResultInfo> errorResult);
 
   // Implement isa/cast/dyncast/etc.
@@ -3713,7 +3797,23 @@
   }
 };
 DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBlockStorageType, Type)
-  
+
+/// A singleton 'token' type, which establishes a formal dependency
+/// between two SIL nodes.  A token 'value' cannot be abstracted in
+/// SIL: it cannot be returned, yielded, or passed as a function or
+/// block argument.
+class SILTokenType final : public TypeBase {
+  friend class ASTContext;
+  SILTokenType(const ASTContext &C)
+    : TypeBase(TypeKind::SILToken, &C, RecursiveTypeProperties()) {}
+public:
+  // The singleton instance of this type is ASTContext::TheSILTokenType.
+
+  static bool classof(const TypeBase *T) {
+    return T->getKind() == TypeKind::SILToken;
+  }
+};
+DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILTokenType, Type)
 
 /// A type with a special syntax that is always sugar for a library type.
 ///
diff --git a/include/swift/Basic/OptimizationMode.h b/include/swift/Basic/OptimizationMode.h
new file mode 100644
index 0000000..e57b8e6
--- /dev/null
+++ b/include/swift/Basic/OptimizationMode.h
@@ -0,0 +1,32 @@
+//===-------- OptimizationMode.h - Swift optimization modes -----*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_BASIC_OPTIMIZATIONMODE_H
+#define SWIFT_BASIC_OPTIMIZATIONMODE_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace swift {
+
+// The optimization mode specified on the command line or with function
+// attributes.
+enum class OptimizationMode : uint8_t {
+  NotSet = 0,
+  NoOptimization = 1,  // -Onone
+  ForSpeed = 2,        // -Ospeed == -O
+  ForSize = 3,         // -Osize
+  LastMode = ForSize
+};
+
+} // end namespace swift
+
+#endif // SWIFT_BASIC_OPTIMIZATIONMODE_H
diff --git a/include/swift/Basic/SourceLoc.h b/include/swift/Basic/SourceLoc.h
index 8fd7b6f..295e46c 100644
--- a/include/swift/Basic/SourceLoc.h
+++ b/include/swift/Basic/SourceLoc.h
@@ -96,6 +96,10 @@
   bool isValid() const { return Start.isValid(); }
   bool isInvalid() const { return !isValid(); }
 
+  /// Extend this SourceRange to the smallest continuous SourceRange that
+  /// includes both this range and the other one.
+  void widen(SourceRange Other);
+
   bool operator==(const SourceRange &other) const {
     return Start == other.Start && End == other.End;
   }
diff --git a/include/swift/Basic/Statistic.h b/include/swift/Basic/Statistic.h
index 1dd95e0..fff7e4c 100644
--- a/include/swift/Basic/Statistic.h
+++ b/include/swift/Basic/Statistic.h
@@ -105,6 +105,8 @@
   };
 
 private:
+  bool currentProcessExitStatusSet;
+  int currentProcessExitStatus;
   SmallString<128> StatsFilename;
   SmallString<128> TraceFilename;
   llvm::TimeRecord StartedTime;
@@ -140,6 +142,7 @@
   AlwaysOnDriverCounters &getDriverCounters();
   AlwaysOnFrontendCounters &getFrontendCounters();
   AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers();
+  void noteCurrentProcessExitStatus(int);
   FrontendStatsTracer getStatsTracer(StringRef N,
                                      SourceRange const &R);
   void saveAnyFrontendStatsEvents(FrontendStatsTracer const& T,
diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def
index 7d323e5..36033a2 100644
--- a/include/swift/Basic/Statistics.def
+++ b/include/swift/Basic/Statistics.def
@@ -40,6 +40,10 @@
 /// run-over-run.
 DRIVER_STATISTIC(NumDriverJobsSkipped)
 
+/// Total number of driver processes that exited with EXIT_FAILURE / not with
+/// EXIT_SUCCESS.
+DRIVER_STATISTIC(NumProcessFailures)
+
 /// Next 10 statistics count dirtying-events in the driver's dependency graph,
 /// which it uses to decide which files are invalid (and thus which files to
 /// build). There are two dimensions to each dirtying event:
@@ -69,6 +73,10 @@
 /// Driver statistics are collected for frontend processes
 #ifdef FRONTEND_STATISTIC
 
+/// Total number of frontend processes that exited with EXIT_FAILURE / not with
+/// EXIT_SUCCESS.
+FRONTEND_STATISTIC(Frontend, NumProcessFailures)
+
 /// Number of source buffers visible in the source manager.
 FRONTEND_STATISTIC(AST, NumSourceBuffers)
 
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 18bf858..95c5117 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -180,6 +180,7 @@
 NODE(ReflectionMetadataSuperclassDescriptor)
 NODE(GenericTypeParamDecl)
 CONTEXT_NODE(CurryThunk)
+CONTEXT_NODE(DispatchThunk)
 NODE(ThrowsAnnotation)
 NODE(EmptyList)
 NODE(FirstElementMarker)
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 0bd2c66..576fa9c 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -309,6 +309,17 @@
     }
     return SourceFile::ImplicitModuleImportKind::Stdlib;
   }
+
+  /// Performs input setup common to these tools:
+  /// sil-opt, sil-func-extractor, sil-llvm-gen, and sil-nm.
+  /// Return value includes the buffer so caller can keep it alive.
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+  setUpInputForSILTool(StringRef InputFilename, StringRef ModuleNameArg,
+                       bool alwaysSetModuleToMain,
+                       serialization::ExtendedValidationInfo &extendedInfo);
+  bool hasSerializedAST() {
+    return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
+  }
 };
 
 /// A class which manages the state and execution of the compiler.
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 76e6733..ce4b982 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -296,15 +296,18 @@
   /// too complex.
   unsigned SolverExpressionTimeThreshold = 0;
 
-  enum ActionType {
-    NoneAction, ///< No specific action
-    Parse, ///< Parse only
-    Typecheck, ///< Parse and type-check only
-    DumpParse, ///< Parse only and dump AST
+  /// The module for which we should verify all of the generic signatures.
+  std::string VerifyGenericSignaturesInModule;
+
+  enum class ActionType {
+    NoneAction,        ///< No specific action
+    Parse,             ///< Parse only
+    Typecheck,         ///< Parse and type-check only
+    DumpParse,         ///< Parse only and dump AST
     DumpInterfaceHash, ///< Parse and dump the interface token hash.
-    EmitSyntax, ///< Parse and dump Syntax tree as JSON
-    DumpAST, ///< Parse, type-check, and dump AST
-    PrintAST, ///< Parse, type-check, and pretty-print AST
+    EmitSyntax,        ///< Parse and dump Syntax tree as JSON
+    DumpAST,           ///< Parse, type-check, and dump AST
+    PrintAST,          ///< Parse, type-check, and pretty-print AST
 
     /// Parse and dump scope map.
     DumpScopeMaps,
@@ -313,30 +316,30 @@
     DumpTypeRefinementContexts,
 
     EmitImportedModules, ///< Emit the modules that this one imports
-    EmitPCH, ///< Emit PCH of imported bridging header
+    EmitPCH,             ///< Emit PCH of imported bridging header
 
     EmitSILGen, ///< Emit raw SIL
-    EmitSIL, ///< Emit canonical SIL
+    EmitSIL,    ///< Emit canonical SIL
 
     EmitModuleOnly, ///< Emit module only
-    MergeModules, ///< Merge modules only
+    MergeModules,   ///< Merge modules only
 
     EmitSIBGen, ///< Emit serialized AST + raw SIL
-    EmitSIB, ///< Emit serialized AST + canonical SIL
+    EmitSIB,    ///< Emit serialized AST + canonical SIL
 
     Immediate, ///< Immediate mode
-    REPL, ///< REPL mode
+    REPL,      ///< REPL mode
 
     EmitAssembly, ///< Emit assembly
-    EmitIR, ///< Emit LLVM IR
-    EmitBC, ///< Emit LLVM BC
-    EmitObject, ///< Emit object file
+    EmitIR,       ///< Emit LLVM IR
+    EmitBC,       ///< Emit LLVM BC
+    EmitObject,   ///< Emit object file
   };
 
-  bool isCreatingSIL() { return RequestedAction >= EmitSILGen; }
+  bool isCreatingSIL() { return RequestedAction >= ActionType::EmitSILGen; }
 
   /// Indicates the action the user requested that the frontend perform.
-  ActionType RequestedAction = NoneAction;
+  ActionType RequestedAction = ActionType::NoneAction;
 
   /// Indicates that the input(s) should be parsed as the Swift stdlib.
   bool ParseStdlib = false;
diff --git a/include/swift/IDE/RefactoringKinds.def b/include/swift/IDE/RefactoringKinds.def
index ea9b50d..0e6a1ae 100644
--- a/include/swift/IDE/RefactoringKinds.def
+++ b/include/swift/IDE/RefactoringKinds.def
@@ -52,6 +52,8 @@
 
 RANGE_REFACTORING(ExtractRepeatedExpr, "Extract Repeated Expression", extract.expr.repeated)
 
+RANGE_REFACTORING(MoveMembersToExtension, "Move To Extension", move.members.to.extension)
+
 RANGE_REFACTORING(ConvertStringsConcatenationToInterpolation, "Convert to String Interpolation", convert.string-concatenation.interpolation)
 #undef CURSOR_REFACTORING
 #undef RANGE_REFACTORING
diff --git a/include/swift/AST/SourceEntityWalker.h b/include/swift/IDE/SourceEntityWalker.h
similarity index 94%
rename from include/swift/AST/SourceEntityWalker.h
rename to include/swift/IDE/SourceEntityWalker.h
index fd33571..61f8cc5 100644
--- a/include/swift/AST/SourceEntityWalker.h
+++ b/include/swift/IDE/SourceEntityWalker.h
@@ -10,8 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef SWIFT_AST_SOURCE_ENTITY_WALKER_H
-#define SWIFT_AST_SOURCE_ENTITY_WALKER_H
+#ifndef SWIFT_IDE_SOURCE_ENTITY_WALKER_H
+#define SWIFT_IDE_SOURCE_ENTITY_WALKER_H
 
 #include "swift/AST/ASTWalker.h"
 #include "swift/Basic/LLVM.h"
@@ -36,6 +36,7 @@
   class Stmt;
   class Expr;
   class Type;
+  struct ASTNode;
 
 
 /// An abstract class used to traverse the AST and provide source information.
@@ -61,6 +62,9 @@
   /// Walks the provided Expr.
   /// \returns true if traversal was aborted, false otherwise.
   bool walk(Expr *E);
+  /// Walks the provided ASTNode.
+  /// \returns true if traversal was aborted, false otherwise.
+  bool walk(ASTNode N);
 
   /// This method is called when first visiting a decl, before walking into its
   /// children.  If it returns false, the subtree is skipped.
@@ -109,9 +113,11 @@
   ///
   /// \param D the referenced decl.
   /// \param Range the source range of the source reference.
+  /// \param AccKind whether this is a read, write or read/write access.
   /// \param IsOpenBracket this is \c true when the method is called on an
   /// open bracket.
   virtual bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+                                       Optional<AccessKind> AccKind,
                                        bool IsOpenBracket);
 
   /// This method is called for each keyword argument in a call expression.
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index f5e1204..4134871 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -19,7 +19,7 @@
 #include "swift/AST/DeclNameLoc.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/ASTPrinter.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Parse/Token.h"
 #include "llvm/ADT/StringRef.h"
 #include <memory>
@@ -242,6 +242,7 @@
   bool tryResolve(ModuleEntity Mod, SourceLoc Loc);
   bool tryResolve(Stmt *St);
   bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+                               Optional<AccessKind> AccKind,
                                bool IsOpenBracket) override;
 };
 
@@ -316,7 +317,7 @@
   std::vector<ResolvedLoc> resolve(ArrayRef<UnresolvedLoc> Locs, ArrayRef<Token> Tokens);
 };
 
-enum class RangeKind : int8_t{
+enum class RangeKind : int8_t {
   Invalid = -1,
   SingleExpression,
   SingleStatement,
@@ -324,6 +325,8 @@
 
   MultiStatement,
   PartOfExpression,
+
+  MultiTypeMemberDecl,
 };
 
 struct DeclaredDecl {
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 6631236..31e028f 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -577,16 +577,6 @@
     return reinterpret_cast<SILFunction*>(Pointer);
   }
 
-  /// Returns true if this function is only serialized, but not necessarily
-  /// code-gen'd. These are fragile transparent functions.
-  bool isSILOnly() const {
-    if (getKind() != Kind::SILFunction)
-      return false;
-
-    SILFunction *F = getSILFunction();
-    return F->isTransparent() && F->isDefinition() && F->isSerialized();
-  }
-
   SILGlobalVariable *getSILGlobalVariable() const {
     assert(getKind() == Kind::SILGlobalVariable);
     return reinterpret_cast<SILGlobalVariable*>(Pointer);
@@ -681,7 +671,6 @@
   static LinkInfo get(const UniversalLinkageInfo &linkInfo,
                       StringRef name,
                       SILLinkage linkage,
-                      bool isSILOnly,
                       ForDefinition_t isDefinition,
                       bool isWeakImported);
 
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 018ec22..159dbcd 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -76,6 +76,9 @@
   HelpText<"Like -verify, but updates the original source file">;
 def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,
   HelpText<"Allow diagnostics for '<unknown>' location in verify mode">;
+def verify_generic_signatures : Separate<["-"], "verify-generic-signatures">,
+  MetaVarName<"<module-name>">,
+  HelpText<"Verify the generic signatures in the given module">;
 
 def show_diagnostics_after_fatal : Flag<["-"], "show-diagnostics-after-fatal">,
   HelpText<"Keep emitting subsequent diagnostics after a fatal error">;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 0fa561a..4b2f273 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -58,6 +58,7 @@
     class SyntaxParsingContext;
     struct RawSyntaxInfo;
     struct RawTokenSyntax;
+    enum class SyntaxKind;
   }// end of syntax namespace
 
   /// Different contexts in which BraceItemList are parsed.
@@ -416,12 +417,7 @@
     BacktrackingScope(Parser &P)
       : P(P), PP(P.getParserPosition()), DT(P.Diags) {}
 
-    ~BacktrackingScope() {
-      if (Backtrack) {
-        P.backtrackToPosition(PP);
-        DT.abort();
-      }
-    }
+    ~BacktrackingScope();
 
     void cancelBacktrack() {
       Backtrack = false;
@@ -674,6 +670,7 @@
   /// \brief Parse a comma separated list of some elements.
   ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
                          bool AllowSepAfterLast, Diag<> ErrorDiag,
+                         syntax::SyntaxKind Kind,
                          std::function<ParserStatus()> callback);
 
   void consumeTopLevelDecl(ParserPosition BeginParserPosition,
@@ -1247,7 +1244,8 @@
                                       SourceLoc &inLoc);
 
   Expr *parseExprAnonClosureArg();
-  ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok);
+  ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
+                                   syntax::SyntaxKind Kind);
 
   /// Parse an expression list, keeping all of the pieces separated.
   ParserStatus parseExprList(tok leftTok, tok rightTok,
@@ -1258,7 +1256,8 @@
                              SmallVectorImpl<Identifier> &exprLabels,
                              SmallVectorImpl<SourceLoc> &exprLabelLocs,
                              SourceLoc &rightLoc,
-                             Expr *&trailingClosure);
+                             Expr *&trailingClosure,
+                             syntax::SyntaxKind Kind);
 
   ParserResult<Expr> parseTrailingClosure(SourceRange calleeRange);
 
@@ -1276,10 +1275,8 @@
   ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
                                          bool isExprBasic);
   ParserResult<Expr> parseExprCollection(SourceLoc LSquareLoc = SourceLoc());
-  ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc,
-                                    ParserResult<Expr> FirstExpr);
-  ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc,
-                                         ParserResult<Expr> FirstKey);
+  ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc);
+  ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc);
 
   UnresolvedDeclRefExpr *parseExprOperator();
 
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index 920c1d2..fd459d9 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -66,7 +66,7 @@
 
   unsigned getSizeOfHeapObject() {
     // This must match sizeof(HeapObject) for the target.
-    return sizeof(StoredPointer) + 8;
+    return sizeof(StoredPointer) * 2;
   }
 
   void dumpAllSections(std::ostream &OS) {
@@ -483,9 +483,8 @@
     case MetadataSourceKind::ClosureBinding: {
       unsigned Index = cast<ClosureBindingMetadataSource>(MS)->getIndex();
 
-      // Skip the context's isa pointer (4 or 8 bytes) and reference counts
-      // (4 bytes each regardless of platform word size). This is just
-      // sizeof(HeapObject) in the target.
+      // Skip the context's HeapObject header
+      // (one word each for isa pointer and reference counts).
       //
       // Metadata and conformance tables are stored consecutively after
       // the heap object header, in the 'necessary bindings' area.
diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h
index d96fc9e..e88adeb 100644
--- a/include/swift/Reflection/TypeRef.h
+++ b/include/swift/Reflection/TypeRef.h
@@ -344,7 +344,7 @@
     for (const auto &Param : Parameters) {
       ID.addString(Param.getLabel().str());
       ID.addPointer(Param.getType());
-      ID.addInteger(static_cast<uint32_t>(Param.getFlags().toRaw()));
+      ID.addInteger(static_cast<uint32_t>(Param.getFlags().getIntValue()));
     }
     ID.addPointer(Result);
     ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index d8ac5a3..e77064b 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -17,7 +17,6 @@
 #ifndef SWIFT_REMOTE_METADATAREADER_H
 #define SWIFT_REMOTE_METADATAREADER_H
 
-#include "swift/AST/Types.h"
 #include "swift/Runtime/Metadata.h"
 #include "swift/Remote/MemoryReader.h"
 #include "swift/Demangling/Demangler.h"
@@ -33,9 +32,9 @@
 template <typename BuiltType> class FunctionParam {
   StringRef Label;
   BuiltType Type;
-  ParameterTypeFlags Flags;
+  ParameterFlags Flags;
 
-  FunctionParam(StringRef label, BuiltType type, ParameterTypeFlags flags)
+  FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
       : Label(label), Type(type), Flags(flags) {}
 
 public:
@@ -45,7 +44,7 @@
 
   StringRef getLabel() const { return Label; }
   BuiltType getType() const { return Type; }
-  ParameterTypeFlags getFlags() const { return Flags; }
+  ParameterFlags getFlags() const { return Flags; }
 
   void setLabel(StringRef label) { Label = label; }
   void setType(BuiltType type) { Type = type; }
@@ -53,6 +52,7 @@
   void setVariadic() { Flags = Flags.withVariadic(true); }
   void setShared() { Flags = Flags.withShared(true); }
   void setInOut() { Flags = Flags.withInOut(true); }
+  void setFlags(ParameterFlags flags) { Flags = flags; };
 
   FunctionParam withLabel(StringRef label) const {
     return FunctionParam(label, Type, Flags);
@@ -62,7 +62,7 @@
     return FunctionParam(Label, type, Flags);
   }
 
-  FunctionParam withFlags(ParameterTypeFlags flags) const {
+  FunctionParam withFlags(ParameterFlags flags) const {
     return FunctionParam(Label, Type, flags);
   }
 };
@@ -800,38 +800,25 @@
       auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);
 
       std::vector<FunctionParam<BuiltType>> Parameters;
-      StoredPointer ArgumentAddress = MetadataAddress +
-        sizeof(TargetFunctionTypeMetadata<Runtime>);
-      for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
-           ArgumentAddress += sizeof(StoredPointer)) {
-        StoredPointer FlaggedArgumentAddress;
-        if (!Reader->readInteger(RemoteAddress(ArgumentAddress),
-                                 &FlaggedArgumentAddress))
+      for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) {
+        auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i));
+        if (!ParamTypeRef)
           return BuiltType();
 
         FunctionParam<BuiltType> Param;
-
-        // TODO: Use target-agnostic FlaggedPointer to mask this!
-        const auto InOutMask = (StoredPointer) 1;
-        // FIXME: Add import parameter related flags from metadata
-        if ((FlaggedArgumentAddress & InOutMask) != 0)
-          Param.setInOut();
-
-        FlaggedArgumentAddress &= ~InOutMask;
-        if (auto ParamTypeRef = readTypeFromMetadata(FlaggedArgumentAddress)) {
-          Param.setType(ParamTypeRef);
-          Parameters.push_back(std::move(Param));
-        } else {
-          return BuiltType();
-        }
+        Param.setType(ParamTypeRef);
+        Param.setFlags(Function->getParameterFlags(i));
+        Parameters.push_back(std::move(Param));
       }
 
       auto Result = readTypeFromMetadata(Function->ResultType);
       if (!Result)
         return BuiltType();
 
-      auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
-                                      .withThrows(Function->throws());
+      auto flags = FunctionTypeFlags()
+                       .withConvention(Function->getConvention())
+                       .withThrows(Function->throws())
+                       .withParameterFlags(Function->hasParameterFlags());
       auto BuiltFunction =
           Builder.createFunctionType(Parameters, Result, flags);
       TypeCache[MetadataAddress] = BuiltFunction;
@@ -1195,8 +1182,26 @@
         return _readMetadata<TargetExistentialMetatypeMetadata>(address);
       case MetadataKind::ForeignClass:
         return _readMetadata<TargetForeignClassMetadata>(address);
-      case MetadataKind::Function:
-        return _readMetadata<TargetFunctionTypeMetadata>(address);
+      case MetadataKind::Function: {
+        StoredSize flagsValue;
+        auto flagsAddr =
+            address + TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
+        if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue))
+          return nullptr;
+
+        auto flags =
+            TargetFunctionTypeFlags<StoredSize>::fromIntValue(flagsValue);
+
+        using Parameter =
+            ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
+        auto totalSize = sizeof(TargetFunctionTypeMetadata<Runtime>) +
+                         flags.getNumParameters() * sizeof(Parameter);
+
+        if (flags.hasParameterFlags())
+          totalSize += flags.getNumParameters() * sizeof(uint32_t);
+
+        return _readMetadata(address, totalSize);
+      }
       case MetadataKind::HeapGenericLocalVariable:
         return _readMetadata<TargetGenericBoxHeapMetadata>(address);
       case MetadataKind::HeapLocalVariable:
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 77a4904..eb786f2 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1745,36 +1745,53 @@
 template <typename Runtime>
 struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
   using StoredSize = typename Runtime::StoredSize;
-
-  // TODO: Make this target agnostic
-  using Argument = FlaggedPointer<const TargetMetadata<Runtime> *, 0>;
+  using Parameter = ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
 
   TargetFunctionTypeFlags<StoredSize> Flags;
 
   /// The type metadata for the result type.
   ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ResultType;
 
-  TargetPointer<Runtime, Argument> getArguments() {
-    return reinterpret_cast<TargetPointer<Runtime, Argument>>(this + 1);
+  Parameter *getParameters() { return reinterpret_cast<Parameter *>(this + 1); }
+
+  const Parameter *getParameters() const {
+    return reinterpret_cast<const Parameter *>(this + 1);
   }
 
-  TargetPointer<Runtime, const Argument> getArguments() const {
-    return reinterpret_cast<TargetPointer<Runtime, const Argument>>(this + 1);
+  Parameter getParameter(unsigned index) const {
+    assert(index < getNumParameters());
+    return getParameters()[index];
   }
-  
-  StoredSize getNumArguments() const {
-    return Flags.getNumArguments();
+
+  ParameterFlags getParameterFlags(unsigned index) const {
+    assert(index < getNumParameters());
+    auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0;
+    return ParameterFlags::fromIntValue(flags);
+  }
+
+  StoredSize getNumParameters() const {
+    return Flags.getNumParameters();
   }
   FunctionMetadataConvention getConvention() const {
     return Flags.getConvention();
   }
   bool throws() const { return Flags.throws(); }
+  bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
 
   static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);
 
   static bool classof(const TargetMetadata<Runtime> *metadata) {
     return metadata->getKind() == MetadataKind::Function;
   }
+
+  uint32_t *getParameterFlags() {
+    return reinterpret_cast<uint32_t *>(getParameters() + getNumParameters());
+  }
+
+  const uint32_t *getParameterFlags() const {
+    return reinterpret_cast<const uint32_t *>(getParameters() +
+                                              getNumParameters());
+  }
 };
 using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;
 
@@ -2404,7 +2421,9 @@
 struct TargetProtocolConformanceRecord {
 public:
   using WitnessTableAccessorFn
-    = const WitnessTable *(const TargetMetadata<Runtime>*);
+    = const WitnessTable *(const TargetMetadata<Runtime>*,
+                           const WitnessTable **,
+                           size_t);
 
 private:
   /// The protocol being conformed to.
@@ -2639,28 +2658,58 @@
 /// \brief Fetch a uniqued metadata for a function type.
 SWIFT_RUNTIME_EXPORT
 const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]);
+swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+                              const Metadata *const *parameters,
+                              const uint32_t *parameterFlags,
+                              const Metadata *result);
 
 SWIFT_RUNTIME_EXPORT
 const FunctionTypeMetadata *
 swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
-                               const void *arg0,
-                               const Metadata *resultMetadata);
+                               const Metadata *arg0,
+                               const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *
+swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+                                        const Metadata *arg0,
+                                        ParameterFlags flags0,
+                                        const Metadata *result);
 
 SWIFT_RUNTIME_EXPORT
 const FunctionTypeMetadata *
 swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
-                               const void *arg0,
-                               const void *arg1,
-                               const Metadata *resultMetadata);
+                               const Metadata *arg0,
+                               const Metadata *arg1,
+                               const Metadata *result);
 
 SWIFT_RUNTIME_EXPORT
 const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
-                               const void *arg0,
-                               const void *arg1,
-                               const void *arg2,
-                               const Metadata *resultMetadata);
+swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+                                        const Metadata *arg0,
+                                        ParameterFlags flags0,
+                                        const Metadata *arg1,
+                                        ParameterFlags flags1,
+                                        const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3(
+                                                FunctionTypeFlags flags,
+                                                const Metadata *arg0,
+                                                const Metadata *arg1,
+                                                const Metadata *arg2,
+                                                const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3WithFlags(
+                                                FunctionTypeFlags flags,
+                                                const Metadata *arg0,
+                                                ParameterFlags flags0,
+                                                const Metadata *arg1,
+                                                ParameterFlags flags1,
+                                                const Metadata *arg2,
+                                                ParameterFlags flags2,
+                                                const Metadata *result);
 
 /// \brief Fetch a uniqued metadata for a thin function type.
 SWIFT_RUNTIME_EXPORT
@@ -2750,13 +2799,18 @@
 SWIFT_RUNTIME_EXPORT
 void
 swift_instantiateObjCClass(const ClassMetadata *theClass);
-#endif
 
 /// \brief Fetch a uniqued type metadata for an ObjC class.
 SWIFT_RUNTIME_EXPORT
 const Metadata *
 swift_getObjCClassMetadata(const ClassMetadata *theClass);
 
+/// \brief Get the ObjC class object from class type metadata.
+SWIFT_RUNTIME_EXPORT
+const ClassMetadata *
+swift_getObjCClassFromMetadata(const Metadata *theClass);
+#endif
+
 /// \brief Fetch a unique type metadata object for a foreign type.
 SWIFT_RUNTIME_EXPORT
 const ForeignTypeMetadata *
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index dcdd45f..a07686e 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -759,28 +759,84 @@
          ARGS(OpaquePtrTy, SizeTy, TypeMetadataPtrTy),
          ATTRS(NoUnwind))
 
-// Metadata *swift_getFunctionTypeMetadata(const void **args);
+// Metadata *swift_getFunctionTypeMetadata(unsigned long flags,
+//                                         const Metadata **parameters,
+//                                         const uint32_t *parameterFlags,
+//                                         const Metadata *result);
 FUNCTION(GetFunctionMetadata, swift_getFunctionTypeMetadata, DefaultCC,
          RETURNS(TypeMetadataPtrTy),
-         ARGS(Int8PtrTy->getPointerTo(0)),
+         ARGS(SizeTy,
+              TypeMetadataPtrTy->getPointerTo(0),
+              Int32Ty->getPointerTo(0),
+              TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone))
 
-// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags, const void *arg0, const Metadata *resultMetadata);
+// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags,
+//                                          const Metadata *arg0,
+//                                          const Metadata *resultMetadata);
 FUNCTION(GetFunctionMetadata1, swift_getFunctionTypeMetadata1, DefaultCC,
+        RETURNS(TypeMetadataPtrTy),
+        ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+        ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata1WithFlags(unsigned long flags,
+//                                                   const Metadata *arg0,
+//                                                   const uint32_t paramFlags,
+//                                                   const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata1WithFlags, swift_getFunctionTypeMetadata1WithFlags,
+         DefaultCC,
          RETURNS(TypeMetadataPtrTy),
-         ARGS(SizeTy, Int8PtrTy, TypeMetadataPtrTy),
+         ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone))
 
-// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags, const void *arg0, const void *arg1, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags,
+//                                          const Metadata *arg0,
+//                                          const Metadata *arg1,
+//                                          const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2,
+        DefaultCC,
+        RETURNS(TypeMetadataPtrTy),
+        ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+        ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata2WithFlags(unsigned long flags,
+//                                                   const Metadata *arg0,
+//                                                   const uint32_t flags0,
+//                                                   const Metadata *arg1,
+//                                                   const uint32_t flags1,
+//                                                   const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2WithFlags, swift_getFunctionTypeMetadata2WithFlags,
+         DefaultCC,
          RETURNS(TypeMetadataPtrTy),
-         ARGS(SizeTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+         ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+              TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone))
 
-// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags, const void *arg0, const void *arg1, const void *arg2, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags,
+//                                          const Metadata *arg0,
+//                                          const Metadata *arg1,
+//                                          const Metadata *arg2,
+//                                          const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3,
+        DefaultCC,
+        RETURNS(TypeMetadataPtrTy),
+        ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
+             TypeMetadataPtrTy),
+        ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata3WithFlags(unsigned long flags,
+//                                                   const Metadata *arg0,
+//                                                   const uint32_t flags0,
+//                                                   const Metadata *arg1,
+//                                                   const uint32_t flags1,
+//                                                   const Metadata *arg2,
+//                                                   const uint32_t flags2,
+//                                                   const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3WithFlags, swift_getFunctionTypeMetadata3WithFlags,
+         DefaultCC,
          RETURNS(TypeMetadataPtrTy),
-         ARGS(SizeTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+         ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+              TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone))
 
 // Metadata *swift_getForeignTypeMetadata(Metadata *nonUnique);
@@ -841,6 +897,12 @@
          ARGS(ObjCClassPtrTy),
          ATTRS(NoUnwind, ReadNone))
 
+// Metadata *swift_getObjCClassFromMetadata(objc_class *theClass);
+FUNCTION(GetObjCClassFromMetadata, swift_getObjCClassFromMetadata, DefaultCC,
+         RETURNS(ObjCClassPtrTy),
+         ARGS(TypeMetadataPtrTy),
+         ATTRS(NoUnwind, ReadNone))
+
 // Metadata *swift_getTupleTypeMetadata(size_t numElements,
 //                                      Metadata * const *elts,
 //                                      const char *labels,
diff --git a/include/swift/SIL/SILBasicBlock.h b/include/swift/SIL/SILBasicBlock.h
index ae02555..5de833b 100644
--- a/include/swift/SIL/SILBasicBlock.h
+++ b/include/swift/SIL/SILBasicBlock.h
@@ -227,7 +227,7 @@
   void dropAllArguments() { ArgumentList.clear(); }
 
   //===--------------------------------------------------------------------===//
-  // Predecessors and Successors
+  // Successors
   //===--------------------------------------------------------------------===//
 
   using SuccessorListTy = TermInst::SuccessorListTy;
@@ -242,81 +242,63 @@
     return getTerminator()->getSuccessors();
   }
 
-  using const_succ_iterator = ConstSuccessorListTy::const_iterator;
-  using succ_iterator = SuccessorListTy::iterator;
+  using const_succ_iterator = TermInst::const_succ_iterator;
+  using succ_iterator = TermInst::succ_iterator;
 
-  bool succ_empty() const { return getSuccessors().empty(); }
-  succ_iterator succ_begin() { return getSuccessors().begin(); }
-  succ_iterator succ_end() { return getSuccessors().end(); }
-  const_succ_iterator succ_begin() const { return getSuccessors().begin(); }
-  const_succ_iterator succ_end() const { return getSuccessors().end(); }
+  bool succ_empty() const { return getTerminator()->succ_empty(); }
+  succ_iterator succ_begin() { return getTerminator()->succ_begin(); }
+  succ_iterator succ_end() { return getTerminator()->succ_end(); }
+  const_succ_iterator succ_begin() const {
+    return getTerminator()->succ_begin();
+  }
+  const_succ_iterator succ_end() const { return getTerminator()->succ_end(); }
 
-  using succblock_iterator =
-      TransformIterator<SILSuccessor *,
-                        std::function<SILBasicBlock *(const SILSuccessor &)>>;
-  using const_succblock_iterator = TransformIterator<
-      const SILSuccessor *,
-      std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+  using succblock_iterator = TermInst::succblock_iterator;
+  using const_succblock_iterator = TermInst::const_succblock_iterator;
+
   succblock_iterator succblock_begin() {
-    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformIterator(getSuccessors().begin(), F);
+    return getTerminator()->succblock_begin();
   }
   succblock_iterator succblock_end() {
-    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformIterator(getSuccessors().end(), F);
+    return getTerminator()->succblock_end();
   }
   const_succblock_iterator succblock_begin() const {
-    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformIterator(getSuccessors().begin(), F);
+    return getTerminator()->succblock_begin();
   }
   const_succblock_iterator succblock_end() const {
-    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformIterator(getSuccessors().end(), F);
+    return getTerminator()->succblock_end();
   }
 
   SILBasicBlock *getSingleSuccessorBlock() {
-    if (succ_empty() || std::next(succ_begin()) != succ_end())
-      return nullptr;
-    return *succ_begin();
+    return getTerminator()->getSingleSuccessorBlock();
   }
 
   const SILBasicBlock *getSingleSuccessorBlock() const {
-    return const_cast<SILBasicBlock *>(this)->getSingleSuccessorBlock();
+    return getTerminator()->getSingleSuccessorBlock();
   }
 
   /// \brief Returns true if \p BB is a successor of this block.
-  bool isSuccessorBlock(SILBasicBlock *BB) const {
-    auto Range = getSuccessorBlocks();
-    return any_of(Range, [&BB](const SILBasicBlock *SuccBB) -> bool {
-      return BB == SuccBB;
-    });
+  bool isSuccessorBlock(SILBasicBlock *Block) const {
+    return getTerminator()->isSuccessorBlock(Block);
   }
 
-  using SuccessorBlockListTy =
-    TransformRange<SuccessorListTy,
-                   std::function<SILBasicBlock *(const SILSuccessor &)>>;
-  using ConstSuccessorBlockListTy =
-    TransformRange<ConstSuccessorListTy,
-                   std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+  using SuccessorBlockListTy = TermInst::SuccessorBlockListTy;
+  using ConstSuccessorBlockListTy = TermInst::ConstSuccessorBlockListTy;
 
   /// Return the range of SILBasicBlocks that are successors of this block.
   SuccessorBlockListTy getSuccessorBlocks() {
-    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformRange(getSuccessors(), F);
+    return getTerminator()->getSuccessorBlocks();
   }
 
   /// Return the range of SILBasicBlocks that are successors of this block.
   ConstSuccessorBlockListTy getSuccessorBlocks() const {
-    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
-    FuncTy F(&SILSuccessor::getBB);
-    return makeTransformRange(getSuccessors(), F);
+    return getTerminator()->getSuccessorBlocks();
   }
 
+  //===--------------------------------------------------------------------===//
+  // Predecessors
+  //===--------------------------------------------------------------------===//
+
   using pred_iterator = SILSuccessor::pred_iterator;
 
   bool pred_empty() const { return PredList == nullptr; }
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index da792da..27a8a51 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -381,6 +381,25 @@
                                            SpecializationInfo));
   }
 
+  BeginApplyInst *createBeginApply(
+      SILLocation Loc, SILValue Fn, SubstitutionList Subs,
+      ArrayRef<SILValue> Args, bool isNonThrowing,
+      const GenericSpecializationInformation *SpecializationInfo = nullptr) {
+    return insert(BeginApplyInst::create(getSILDebugLocation(Loc), Fn, Subs,
+                                         Args, isNonThrowing, silConv, *F,
+                                         OpenedArchetypes, SpecializationInfo));
+  }
+
+  AbortApplyInst *createAbortApply(SILLocation loc, SILValue beginApply) {
+    return insert(new (getModule()) AbortApplyInst(getSILDebugLocation(loc),
+                                                   beginApply));
+  }
+
+  EndApplyInst *createEndApply(SILLocation loc, SILValue beginApply) {
+    return insert(new (getModule()) EndApplyInst(getSILDebugLocation(loc),
+                                                 beginApply));
+  }
+
   BuiltinInst *createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy,
                              SubstitutionList Subs,
                              ArrayRef<SILValue> Args) {
@@ -1218,6 +1237,16 @@
         getModule(), getSILDebugLocation(Loc), Operand));
   }
 
+  MultipleValueInstruction *emitDestructureValueOperation(SILLocation Loc,
+                                                          SILValue Operand) {
+    SILType OpTy = Operand->getType();
+    if (OpTy.is<TupleType>())
+      return createDestructureTuple(Loc, Operand);
+    if (OpTy.getStructOrBoundGenericStruct())
+      return createDestructureStruct(Loc, Operand);
+    llvm_unreachable("Can not emit a destructure for this type of operand.");
+  }
+
   ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
                                      SILDeclRef Member, SILType MethodTy) {
     return insert(new (getModule()) ClassMethodInst(
@@ -1617,6 +1646,18 @@
         new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
   }
 
+  UnwindInst *createUnwind(SILLocation loc) {
+    return insertTerminator(
+        new (getModule()) UnwindInst(getSILDebugLocation(loc)));
+  }
+
+  YieldInst *createYield(SILLocation loc, ArrayRef<SILValue> yieldedValues,
+                         SILBasicBlock *resumeBB, SILBasicBlock *unwindBB) {
+    return insertTerminator(
+        YieldInst::create(getSILDebugLocation(loc), yieldedValues,
+                          resumeBB, unwindBB, getFunction()));
+  }
+
   CondBranchInst *
   createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
                    SILBasicBlock *Target2,
@@ -1864,6 +1905,53 @@
     lowering.emitDestroyValue(*this, Loc, v);
   }
 
+  /// Convenience function for handling begin_borrow instructions in ownership
+  /// and non-ownership SIL. In non-ownership SIL we just forward the input
+  /// value. Otherwise, we emit the begin_borrow instruction.
+  SILValue emitBeginBorrowOperation(SILLocation Loc, SILValue Value) {
+    assert(!Value->getType().isAddress());
+    // If ownership is not enabled in the function, just return our original
+    // value.
+    if (getFunction().hasUnqualifiedOwnership())
+      return Value;
+
+    // If we have a trivial value, just return the value. Trivial values have
+    // lifetimes independent of any other values.
+    //
+    // *NOTE* For now to be conservative since we do not have the ownership
+    // verifier everywhere, we use getType()::isTrivial() instead of
+    // getOwnershipKind().
+    if (Value->getType().isTrivial(getModule())) {
+      return Value;
+    }
+
+    // Otherwise, we have a non-trivial value, perform the borrow.
+    return createBeginBorrow(Loc, Value);
+  }
+
+  /// Convenience function for handling end_borrow instructions in ownership and
+  /// non-ownership SIL. In non-ownership SIL we just early exit. Otherwise, we
+  /// emit the end_borrow.
+  void emitEndBorrowOperation(SILLocation Loc, SILValue Borrowed,
+                              SILValue Original) {
+    assert(!Borrowed->getType().isAddress());
+    // If ownership is not enabled, just return.
+    if (getFunction().hasUnqualifiedOwnership())
+      return;
+
+    // If we have a trivial value, just return. Trivial values have lifetimes
+    // independent of any other values.
+    //
+    // *NOTE* For now to be conservative since we do not have the ownership
+    // verifier everywhere, we use getType()::isTrivial() instead of
+    // getOwnershipKind().
+    if (Borrowed->getType().isTrivial(getModule())) {
+      return;
+    }
+
+    createEndBorrow(Loc, Borrowed, Original);
+  }
+
   SILValue emitTupleExtract(SILLocation Loc, SILValue Operand, unsigned FieldNo,
                             SILType ResultTy) {
     // Fold tuple_extract(tuple(x,y,z),2)
@@ -1990,6 +2078,35 @@
   }
 };
 
+class SavedInsertionPointRAII {
+  SILBuilder &Builder;
+  PointerUnion<SILInstruction *, SILBasicBlock *> SavedIP;
+
+public:
+  SavedInsertionPointRAII(SILBuilder &B, SILInstruction *NewIP)
+      : Builder(B), SavedIP(&*B.getInsertionPoint()) {
+    Builder.setInsertionPoint(NewIP);
+  }
+
+  SavedInsertionPointRAII(SILBuilder &B, SILBasicBlock *NewIP)
+      : Builder(B), SavedIP(B.getInsertionBB()) {
+    Builder.setInsertionPoint(NewIP);
+  }
+
+  SavedInsertionPointRAII(const SavedInsertionPointRAII &) = delete;
+  SavedInsertionPointRAII &operator=(const SavedInsertionPointRAII &) = delete;
+  SavedInsertionPointRAII(SavedInsertionPointRAII &&) = delete;
+  SavedInsertionPointRAII &operator=(SavedInsertionPointRAII &&) = delete;
+
+  ~SavedInsertionPointRAII() {
+    if (SavedIP.is<SILInstruction *>()) {
+      Builder.setInsertionPoint(SavedIP.get<SILInstruction *>());
+    } else {
+      Builder.setInsertionPoint(SavedIP.get<SILBasicBlock *>());
+    }
+  }
+};
+
 } // end swift namespace
 
 #endif
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 833719b..0840a54 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -616,6 +616,39 @@
 
 template<typename ImplClass>
 void
+SILCloner<ImplClass>::visitBeginApplyInst(BeginApplyInst *Inst) {
+  auto Args = getOpValueArray<8>(Inst->getArguments());
+  getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+  doPostProcess(Inst,
+    getBuilder().createBeginApply(getOpLocation(Inst->getLoc()),
+                                  getOpValue(Inst->getCallee()),
+                                  getOpSubstitutions(Inst->getSubstitutions()),
+                                  Args,
+                                  Inst->isNonThrowing(),
+                                  GenericSpecializationInformation::create(
+                                    Inst, getBuilder())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitAbortApplyInst(AbortApplyInst *Inst) {
+  getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+  doPostProcess(Inst,
+    getBuilder().createAbortApply(getOpLocation(Inst->getLoc()),
+                                  getOpValue(Inst->getOperand())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitEndApplyInst(EndApplyInst *Inst) {
+  getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+  doPostProcess(Inst,
+    getBuilder().createEndApply(getOpLocation(Inst->getLoc()),
+                                getOpValue(Inst->getOperand())));
+}
+
+template<typename ImplClass>
+void
 SILCloner<ImplClass>::visitFunctionRefInst(FunctionRefInst *Inst) {
   SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction());
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
@@ -2118,6 +2151,27 @@
 
 template<typename ImplClass>
 void
+SILCloner<ImplClass>::visitUnwindInst(UnwindInst *Inst) {
+  getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+  doPostProcess(Inst,
+    getBuilder().createUnwind(getOpLocation(Inst->getLoc())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitYieldInst(YieldInst *Inst) {
+  auto Values = getOpValueArray<8>(Inst->getYieldedValues());
+  auto ResumeBB = getOpBasicBlock(Inst->getResumeBB());
+  auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB());
+
+  getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+  doPostProcess(Inst,
+    getBuilder().createYield(getOpLocation(Inst->getLoc()), Values,
+                             ResumeBB, UnwindBB));
+}
+
+template<typename ImplClass>
+void
 SILCloner<ImplClass>::visitBranchInst(BranchInst *Inst) {
   auto Args = getOpValueArray<8>(Inst->getArgs());
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index 4f95c8a..bc3acf9 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -66,8 +66,6 @@
 /// True if the entry point is natively foreign.
 bool requiresForeignToNativeThunk(ValueDecl *vd);
 
-unsigned getNaturalUncurryLevel(ValueDecl *vd);
-
 enum ForDefinition_t : bool {
   NotForDefinition = false,
   ForDefinition = true
@@ -219,6 +217,7 @@
   enum class ManglingKind {
     Default,
     DynamicThunk,
+    SwiftDispatchThunk,
   };
 
   /// Produce a mangled form of this constant.
@@ -304,7 +303,7 @@
   void print(llvm::raw_ostream &os) const;
   void dump() const;
 
-  unsigned getUncurryLevel() const;
+  unsigned getParameterListCount() const;
 
   ResilienceExpansion getResilienceExpansion() const {
     return ResilienceExpansion(Expansion);
@@ -345,6 +344,10 @@
   /// to foreign C or ObjC calling convention.
   bool isNativeToForeignThunk() const;
 
+  /// True if the decl ref references a method which introduces a new vtable
+  /// entry.
+  bool requiresNewVTableEntry() const;
+
   /// Return a SILDeclRef to the declaration overridden by this one, or
   /// a null SILDeclRef if there is no override.
   SILDeclRef getOverridden() const;
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 2e6ba51..efbd741 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -17,6 +17,7 @@
 #ifndef SWIFT_SIL_SILFUNCTION_H
 #define SWIFT_SIL_SILFUNCTION_H
 
+#include "swift/AST/ResilienceExpansion.h"
 #include "swift/Basic/ProfileCounter.h"
 #include "swift/SIL/SILBasicBlock.h"
 #include "swift/SIL/SILDebugScope.h"
@@ -170,6 +171,10 @@
   /// pre-specialization.
   unsigned KeepAsPublic : 1;
 
+  /// If != OptimizationMode::NotSet, the optimization mode specified with an
+  /// function attribute.
+  OptimizationMode OptMode;
+
   /// This is the number of uses of this SILFunction inside the SIL.
   /// It does not include references from debug scopes.
   unsigned RefCount = 0;
@@ -328,6 +333,12 @@
     return getLoweredFunctionType()->getRepresentation();
   }
 
+  ResilienceExpansion getResilienceExpansion() const {
+    return (isSerialized()
+            ? ResilienceExpansion::Minimal
+            : ResilienceExpansion::Maximal);
+  }
+
   /// Returns true if this function has a calling convention that has a self
   /// argument.
   bool hasSelfParam() const {
@@ -472,10 +483,26 @@
 
   void addSpecializeAttr(SILSpecializeAttr *Attr);
 
+
+  /// Get this function's optimization mode or OptimizationMode::NotSet if it is
+  /// not set for this specific function.
+  OptimizationMode getOptimizationMode() const { return OptMode; }
+
+  /// Returns the optimization mode for the function. If no mode is set for the
+  /// function, returns the global mode, i.e. the mode of the module's options.
+  OptimizationMode getEffectiveOptimizationMode() const;
+
+  void setOptimizationMode(OptimizationMode mode) { OptMode = mode; }
+
   /// \returns True if the function is optimizable (i.e. not marked as no-opt),
   ///          or is raw SIL (so that the mandatory passes still run).
   bool shouldOptimize() const;
 
+  /// Returns true if this function should be optimized for size.
+  bool optimizeForSize() const {
+    return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+  }
+
   /// Returns true if this is a function that should have its ownership
   /// verified.
   bool shouldVerifyOwnership() const;
diff --git a/include/swift/SIL/SILFunctionConventions.h b/include/swift/SIL/SILFunctionConventions.h
index 558541e..d26e981 100644
--- a/include/swift/SIL/SILFunctionConventions.h
+++ b/include/swift/SIL/SILFunctionConventions.h
@@ -45,10 +45,14 @@
 
   static bool isIndirectSILParam(SILParameterInfo param, bool loweredAddresses);
 
+  static bool isIndirectSILYield(SILYieldInfo yield, bool loweredAddresses);
+
   static bool isIndirectSILResult(SILResultInfo result, bool loweredAddresses);
 
   static SILType getSILParamType(SILParameterInfo param, bool loweredAddresses);
 
+  static SILType getSILYieldType(SILYieldInfo yield, bool loweredAddresses);
+
   static SILType getSILResultType(SILResultInfo param, bool loweredAddresses);
 
 public:
@@ -77,6 +81,10 @@
     return isIndirectSILParam(param, loweredAddresses);
   }
 
+  bool isSILIndirect(SILYieldInfo yield) const {
+    return isIndirectSILYield(yield, loweredAddresses);
+  }
+
   bool isSILIndirect(SILResultInfo result) const {
     return isIndirectSILResult(result, loweredAddresses);
   }
@@ -85,6 +93,10 @@
     return getSILParamType(param, loweredAddresses);
   }
 
+  SILType getSILType(SILYieldInfo yield) const {
+    return getSILYieldType(yield, loweredAddresses);
+  }
+
   SILType getSILType(SILResultInfo result) const {
     return getSILResultType(result, loweredAddresses);
   }
@@ -115,6 +127,10 @@
     return silConv.isSILIndirect(param);
   }
 
+  bool isSILIndirect(SILYieldInfo yield) const {
+    return silConv.isSILIndirect(yield);
+  }
+
   bool isSILIndirect(SILResultInfo result) const {
     return silConv.isSILIndirect(result);
   }
@@ -123,6 +139,10 @@
     return silConv.getSILType(param);
   }
 
+  SILType getSILType(SILYieldInfo yield) const {
+    return silConv.getSILType(yield);
+  }
+
   SILType getSILType(SILResultInfo result) const {
     return silConv.getSILType(result);
   }
@@ -279,6 +299,28 @@
   }
 
   //===--------------------------------------------------------------------===//
+  // SIL yield types.
+  //===--------------------------------------------------------------------===//
+
+  unsigned getNumYields() const { return funcTy->getNumYields(); }
+
+  ArrayRef<SILYieldInfo> getYields() const {
+    return funcTy->getYields();
+  }
+
+  using SILYieldTypeIter =
+      llvm::mapped_iterator<const SILYieldInfo *, SILParameterTypeFunc>;
+  using SILYieldTypeRange = IteratorRange<SILYieldTypeIter>;
+
+  SILYieldTypeRange getYieldSILTypes() const {
+    return makeIteratorRange(
+        SILYieldTypeIter(funcTy->getYields().begin(),
+                         SILParameterTypeFunc(silConv)),
+        SILYieldTypeIter(funcTy->getYields().end(),
+                         SILParameterTypeFunc(silConv)));
+  }
+
+  //===--------------------------------------------------------------------===//
   // SILArgument API, including indirect results and parameters.
   //
   // The argument indices below relate to full applies in which the caller and
@@ -363,6 +405,11 @@
   llvm_unreachable("covered switch isn't covered?!");
 }
 
+inline bool SILModuleConventions::isIndirectSILYield(SILYieldInfo yield,
+                                                     bool loweredAddresses) {
+  return isIndirectSILParam(yield, loweredAddresses);
+}
+
 inline bool SILModuleConventions::isIndirectSILResult(SILResultInfo result,
                                                       bool loweredAddresses) {
   switch (result.getConvention()) {
@@ -386,6 +433,11 @@
              : SILType::getPrimitiveObjectType(param.getType());
 }
 
+inline SILType SILModuleConventions::getSILYieldType(SILYieldInfo yield,
+                                                     bool loweredAddresses) {
+  return getSILParamType(yield, loweredAddresses);
+}
+
 inline SILType SILModuleConventions::getSILResultType(SILResultInfo result,
                                                       bool loweredAddresses) {
   return SILModuleConventions::isIndirectSILResult(result, loweredAddresses)
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 1ed4bcb..d27792d 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -133,7 +133,10 @@
 public:
   SILInstructionResultArray() : Pointer(nullptr), Size(0) {}
   SILInstructionResultArray(const SingleValueInstruction *SVI);
-  SILInstructionResultArray(ArrayRef<MultipleValueInstructionResult> MVResults);
+  SILInstructionResultArray(ArrayRef<MultipleValueInstructionResult> results);
+
+  template <class Result>
+  SILInstructionResultArray(ArrayRef<Result> results);
 
   SILInstructionResultArray(const SILInstructionResultArray &Other) = default;
   SILInstructionResultArray &
@@ -153,8 +156,14 @@
   iterator begin() const;
   iterator end() const;
 
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  reverse_iterator rbegin() const;
+  reverse_iterator rend() const;
+
   using range = llvm::iterator_range<iterator>;
   range getValues() const;
+  using reverse_range = llvm::iterator_range<reverse_iterator>;
+  reverse_range getReversedValues() const;
 
   using type_range = llvm::iterator_range<
       llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>>>;
@@ -197,9 +206,7 @@
   }
 };
 
-class SILInstructionResultArray::iterator
-    : public std::iterator<std::bidirectional_iterator_tag, SILValue,
-                           ptrdiff_t> {
+class SILInstructionResultArray::iterator {
   /// Our "parent" array.
   ///
   /// This is actually a value type reference into a SILInstruction of some
@@ -211,14 +218,21 @@
   Optional<unsigned> Index;
 
 public:
+  using difference_type = int;
+  using value_type = SILValue;
+  using pointer = void;
+  using reference = SILValue;
+  using iterator_category = std::bidirectional_iterator_tag;
+
   iterator() = default;
   iterator(const SILInstructionResultArray &Parent,
            Optional<unsigned> Index = 0)
       : Parent(Parent), Index(Index) {}
 
   SILValue operator*() const { return Parent[Index.getValue()]; }
-
+  SILValue operator*() { return Parent[Index.getValue()]; }
   SILValue operator->() const { return operator*(); }
+  SILValue operator->() { return operator*(); }
 
   iterator &operator++() {
     ++Index.getValue();
@@ -794,6 +808,15 @@
   static constexpr uint64_t IndexBitOffset = ValueOwnershipKind::NumBits;
 };
 
+template <class Result>
+SILInstructionResultArray::SILInstructionResultArray(ArrayRef<Result> results)
+  : SILInstructionResultArray(
+        ArrayRef<MultipleValueInstructionResult>(results.data(),
+                                                 results.size())) {
+  static_assert(sizeof(Result) == sizeof(MultipleValueInstructionResult),
+                "MultipleValueInstructionResult subclass has wrong size");
+}
+
 /// An instruction that may produce an arbitrary number of values.
 class MultipleValueInstruction : public SILInstruction {
   friend class SILInstruction;
@@ -825,13 +848,33 @@
   }
 };
 
+template <typename...> class InitialTrailingObjects;
+template <typename...> class FinalTrailingObjects;
+
 /// A utility mixin class that must be used by /all/ subclasses of
 /// MultipleValueInstruction to store their results.
-template <SILInstructionKind Kind, typename Derived, typename DerivedResult,
-          typename... OtherTrailingTypes>
-class MultipleValueInstructionTrailingObjects
-    : protected llvm::TrailingObjects<Derived, MultipleValueInstruction *,
-                                      DerivedResult, OtherTrailingTypes...> {
+///
+/// The exact ordering of trailing types matters quite a lot because
+/// it's vital that the fields used by preceding numTrailingObjects
+/// implementations be initialized before this base class is (and
+/// conversely that this base class be initialized before any of the
+/// succeeding numTrailingObjects implementations are called).
+template <typename Derived, typename DerivedResult,
+          typename Init = InitialTrailingObjects<>,
+          typename Final = FinalTrailingObjects<>>
+class MultipleValueInstructionTrailingObjects;
+
+template <typename Derived, typename DerivedResult,
+          typename... InitialOtherTrailingTypes,
+          typename... FinalOtherTrailingTypes>
+class MultipleValueInstructionTrailingObjects<Derived, DerivedResult,
+                      InitialTrailingObjects<InitialOtherTrailingTypes...>,
+                      FinalTrailingObjects<FinalOtherTrailingTypes...>>
+    : protected llvm::TrailingObjects<Derived,
+                                      InitialOtherTrailingTypes...,
+                                      MultipleValueInstruction *,
+                                      DerivedResult,
+                                      FinalOtherTrailingTypes...> {
   static_assert(LLVM_IS_FINAL(DerivedResult),
                 "Expected DerivedResult to be final");
   static_assert(
@@ -844,8 +887,10 @@
 
 protected:
   using TrailingObjects =
-      llvm::TrailingObjects<Derived, MultipleValueInstruction *, DerivedResult,
-                            OtherTrailingTypes...>;
+      llvm::TrailingObjects<Derived,
+                            InitialOtherTrailingTypes...,
+                            MultipleValueInstruction *, DerivedResult,
+                            FinalOtherTrailingTypes...>;
   friend TrailingObjects;
 
   using TrailingObjects::totalSizeToAlloc;
@@ -905,15 +950,17 @@
   }
 
 public:
+  ArrayRef<DerivedResult> getAllResultsBuffer() const {
+    auto *ptr = this->template getTrailingObjects<DerivedResult>();
+    return { ptr, NumResults };
+  }
+
   SILInstructionResultArray getAllResults() const {
     // Our results start at element 1 since we stash the pointer to our parent
     // MultipleValueInstruction in the 0 elt slot. This allows all
     // MultipleValueInstructionResult to find their parent
     // MultipleValueInstruction by using pointer arithmetic.
-    auto *Result = this->template getTrailingObjects<DerivedResult>();
-    return SILInstructionResultArray(
-        {static_cast<const MultipleValueInstructionResult *>(Result),
-         NumResults});
+    return SILInstructionResultArray(getAllResultsBuffer());
   };
 };
 
@@ -1558,9 +1605,19 @@
   SubstitutionList getSubstitutions() const { return Subs; }
 };
 
-void *allocateApplyInst(SILFunction &F, size_t size, size_t align);
 class PartialApplyInst;
 
+// There's no good reason for the OverloadToken type to be internal
+// or protected, and it makes it very difficult to write our CRTP classes
+// if it is, so pull it out.  TODO: just fix LLVM.
+struct TerribleOverloadTokenHack :
+    llvm::trailing_objects_internal::TrailingObjectsBase {
+  template <class T>
+  using Hack = OverloadToken<T>;
+};
+template <class T>
+using OverloadToken = TerribleOverloadTokenHack::Hack<T>;
+
 /// ApplyInstBase - An abstract class for different kinds of function
 /// application.
 template <class Impl, class Base,
@@ -1587,50 +1644,71 @@
 
   /// Used for apply_inst instructions: true if the called function has an
   /// error result but is not actually throwing.
-  bool NonThrowing: 1;
+  unsigned NonThrowing: 1;
 
   /// The number of call arguments as required by the callee.
   unsigned NumCallArguments;
 
-  /// The fixed operand is the callee;  the rest are arguments.
-  TailAllocatedOperandList<NumStaticOperands> Operands;
+  /// The total number of type-dependent operands.
+  unsigned NumTypeDependentOperands;
 
-  Substitution *getSubstitutionsStorage() {
-    return reinterpret_cast<Substitution*>(Operands.asArray().end());
-  }
+  Impl &asImpl() { return static_cast<Impl &>(*this); }
+  const Impl &asImpl() const { return static_cast<const Impl &>(*this); }
 
-  const Substitution *getSubstitutionsStorage() const {
-    return reinterpret_cast<const Substitution*>(Operands.asArray().end());
+  MutableArrayRef<Substitution> getSubstitutionsBuffer() {
+    return { asImpl().template getTrailingObjects<Substitution>(),
+             NumSubstitutions };
   }
 
 protected:
   template <class... As>
   ApplyInstBase(SILInstructionKind kind, SILDebugLocation DebugLoc, SILValue callee,
-                SILType substCalleeType, SubstitutionList substitutions,
+                SILType substCalleeType, SubstitutionList subs,
                 ArrayRef<SILValue> args,
-                ArrayRef<SILValue> TypeDependentOperands,
-                const GenericSpecializationInformation *SpecializationInfo,
+                ArrayRef<SILValue> typeDependentOperands,
+                const GenericSpecializationInformation *specializationInfo,
                 As... baseArgs)
       : Base(kind, DebugLoc, baseArgs...), SubstCalleeType(substCalleeType),
-        SpecializationInfo(SpecializationInfo),
-        NumSubstitutions(substitutions.size()), NonThrowing(false),
+        SpecializationInfo(specializationInfo),
+        NumSubstitutions(subs.size()), NonThrowing(false),
         NumCallArguments(args.size()),
-        Operands(this, args, TypeDependentOperands, callee) {
-    static_assert(sizeof(Impl) == sizeof(*this),
-        "subclass has extra storage, cannot use TailAllocatedOperandList");
-    memcpy(getSubstitutionsStorage(), substitutions.begin(),
-           sizeof(substitutions[0]) * substitutions.size());
+        NumTypeDependentOperands(typeDependentOperands.size()) {
+
+    // Initialize the operands.
+    auto allOperands = getAllOperands();
+    new (&allOperands[Callee]) Operand(this, callee);
+    for (size_t i : indices(args)) {
+      new (&allOperands[NumStaticOperands + i]) Operand(this, args[i]);
+    }
+    for (size_t i : indices(typeDependentOperands)) {
+      new (&allOperands[NumStaticOperands + args.size() + i])
+        Operand(this, typeDependentOperands[i]);
+    }
+
+    // Initialize the substitutions.
+    memcpy(getSubstitutionsBuffer().data(), subs.begin(),
+           sizeof(subs[0]) * subs.size());
   }
 
-  static void *allocate(SILFunction &F,
-                        SubstitutionList substitutions,
-                        ArrayRef<SILValue> TypeDependentOperands,
-                        ArrayRef<SILValue> args) {
-    return allocateApplyInst(
-        F, sizeof(Impl) + decltype(Operands)::getExtraSize(
-                              args.size() + TypeDependentOperands.size()) +
-               sizeof(substitutions[0]) * substitutions.size(),
-        alignof(Impl));
+  ~ApplyInstBase() {
+    for (auto &operand : getAllOperands())
+      operand.~Operand();
+  }
+
+  template <class, class...>
+  friend class llvm::TrailingObjects;
+
+  unsigned numTrailingObjects(OverloadToken<Substitution>) const {
+    return NumSubstitutions;
+  }
+
+  unsigned numTrailingObjects(OverloadToken<Operand>) const {
+    return getNumAllOperands();
+  }
+
+  static size_t getNumAllOperands(ArrayRef<SILValue> args,
+                                  ArrayRef<SILValue> typeDependentOperands) {
+    return NumStaticOperands + args.size() + typeDependentOperands.size();
   }
 
   void setNonThrowing(bool isNonThrowing) { NonThrowing = isNonThrowing; }
@@ -1641,7 +1719,7 @@
   /// The operand number of the first argument.
   static unsigned getArgumentOperandNumber() { return NumStaticOperands; }
 
-  SILValue getCallee() const { return Operands[Callee].get(); }
+  SILValue getCallee() const { return getAllOperands()[Callee].get(); }
 
   /// Gets the referenced function by looking through partial apply,
   /// convert_function, and thin to thick function until we find a function_ref.
@@ -1689,31 +1767,58 @@
   bool hasSubstitutions() const { return NumSubstitutions != 0; }
 
   /// The substitutions used to bind the generic arguments of this function.
-  MutableArrayRef<Substitution> getSubstitutions() {
-    return {getSubstitutionsStorage(), NumSubstitutions};
+  SubstitutionList getSubstitutions() const {
+    return { asImpl().template getTrailingObjects<Substitution>(),
+             NumSubstitutions };
   }
 
-  SubstitutionList getSubstitutions() const {
-    return {getSubstitutionsStorage(), NumSubstitutions};
+  /// Return the total number of operands of this instruction.
+  unsigned getNumAllOperands() const {
+    return NumStaticOperands + NumCallArguments + NumTypeDependentOperands;
+  }
+
+  /// Return all the operands of this instruction, which are (in order):
+  ///   - the callee
+  ///   - the formal arguments
+  ///   - the type-dependency arguments
+  MutableArrayRef<Operand> getAllOperands() {
+    return { asImpl().template getTrailingObjects<Operand>(),
+             getNumAllOperands() };
+  }
+
+  ArrayRef<Operand> getAllOperands() const {
+    return { asImpl().template getTrailingObjects<Operand>(),
+             getNumAllOperands() };
+  }
+
+  /// Check whether the given operand index is a call-argument index
+  /// and, if so, return that index.
+  Optional<unsigned> getArgumentIndexForOperandIndex(unsigned index) {
+    assert(index < getNumAllOperands());
+    if (index < NumStaticOperands) return None;
+    index -= NumStaticOperands;
+    if (index >= NumCallArguments) return None;
+    return index;
   }
 
   /// The arguments passed to this instruction.
   MutableArrayRef<Operand> getArgumentOperands() {
-    return Operands.getDynamicAsArray().slice(0, getNumCallArguments());
+    return getAllOperands().slice(NumStaticOperands, NumCallArguments);
   }
 
   ArrayRef<Operand> getArgumentOperands() const {
-    return Operands.getDynamicAsArray().slice(0, getNumCallArguments());
+    return getAllOperands().slice(NumStaticOperands, NumCallArguments);
   }
 
   /// The arguments passed to this instruction.
   OperandValueArrayRef getArguments() const {
-    return OperandValueArrayRef(
-        Operands.getDynamicAsArray().slice(0, getNumCallArguments()));
+    return OperandValueArrayRef(getArgumentOperands());
   }
 
-  /// Returns the number of arguments for this partial apply.
-  unsigned getNumArguments() const { return getArguments().size(); }
+  /// Returns the number of arguments being passed by this apply.
+  /// If this is a partial_apply, it can be less than the number of
+  /// parameters.
+  unsigned getNumArguments() const { return NumCallArguments; }
 
   Operand &getArgumentRef(unsigned i) {
     return getArgumentOperands()[i];
@@ -1727,20 +1832,12 @@
     return getArgumentOperands()[i].set(V);
   }
 
-  ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
-
-  MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
-  unsigned getNumCallArguments() const {
-    return NumCallArguments;
-  }
-
   ArrayRef<Operand> getTypeDependentOperands() const {
-    return Operands.getDynamicAsArray().slice(NumCallArguments);
+    return getAllOperands().slice(NumStaticOperands + NumCallArguments);
   }
 
   MutableArrayRef<Operand> getTypeDependentOperands() {
-    return Operands.getDynamicAsArray().slice(NumCallArguments);
+    return getAllOperands().slice(NumStaticOperands + NumCallArguments);
   }
 
   const GenericSpecializationInformation *getSpecializationInfo() const {
@@ -1861,9 +1958,10 @@
 };
 
 /// ApplyInst - Represents the full application of a function value.
-class ApplyInst
+class ApplyInst final
     : public InstructionBase<SILInstructionKind::ApplyInst,
-                             ApplyInstBase<ApplyInst, SingleValueInstruction>> {
+                             ApplyInstBase<ApplyInst, SingleValueInstruction>>,
+      public llvm::TrailingObjects<ApplyInst, Operand, Substitution> {
   friend SILBuilder;
 
   ApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1891,10 +1989,11 @@
 
 /// PartialApplyInst - Represents the creation of a closure object by partial
 /// application of a function value.
-class PartialApplyInst
+class PartialApplyInst final
     : public InstructionBase<SILInstructionKind::PartialApplyInst,
                              ApplyInstBase<PartialApplyInst,
-                                           SingleValueInstruction>> {
+                                           SingleValueInstruction>>,
+      public llvm::TrailingObjects<PartialApplyInst, Operand, Substitution> {
   friend SILBuilder;
 
   PartialApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1921,6 +2020,129 @@
   }
 };
 
+class BeginApplyInst;
+class BeginApplyResult final : public MultipleValueInstructionResult {
+public:
+  BeginApplyResult(unsigned index, SILType type,
+                   ValueOwnershipKind ownershipKind)
+      : MultipleValueInstructionResult(ValueKind::BeginApplyResult,
+                                       index, type, ownershipKind) {}
+
+  BeginApplyInst *getParent(); // inline below
+  const BeginApplyInst *getParent() const {
+    return const_cast<BeginApplyResult *>(this)->getParent();
+  }
+
+  /// Is this result the token result of the begin_apply, which abstracts
+  /// over the implicit coroutine state?
+  bool isTokenResult() const; // inline below
+
+  static bool classof(const SILNode *N) {
+    return N->getKind() == SILNodeKind::BeginApplyResult;
+  }
+};
+
+/// BeginApplyInst - Represents the beginning of the full application of
+/// a yield_once coroutine (up until the coroutine yields a value back).
+class BeginApplyInst final
+    : public InstructionBase<SILInstructionKind::BeginApplyInst,
+                             ApplyInstBase<BeginApplyInst,
+                                           MultipleValueInstruction>>,
+      public MultipleValueInstructionTrailingObjects<
+          BeginApplyInst, BeginApplyResult,
+          // These must be earlier trailing objects because their
+          // count fields are initialized by an earlier base class.
+          InitialTrailingObjects<Operand, Substitution>> {
+  friend SILBuilder;
+
+  template <class, class...>
+  friend class llvm::TrailingObjects;
+  using InstructionBase::numTrailingObjects;
+  using MultipleValueInstructionTrailingObjects::numTrailingObjects;
+
+  friend class ApplyInstBase<BeginApplyInst, MultipleValueInstruction, false>;
+  using MultipleValueInstructionTrailingObjects::getTrailingObjects;
+
+  BeginApplyInst(SILDebugLocation debugLoc, SILValue callee,
+                 SILType substCalleeType,
+                 ArrayRef<SILType> allResultTypes,
+                 ArrayRef<ValueOwnershipKind> allResultOwnerships,
+                 SubstitutionList substitutions,
+                 ArrayRef<SILValue> args,
+                 ArrayRef<SILValue> typeDependentOperands,
+                 bool isNonThrowing,
+                 const GenericSpecializationInformation *specializationInfo);
+
+  static BeginApplyInst *
+  create(SILDebugLocation debugLoc, SILValue Callee,
+         SubstitutionList substitutions, ArrayRef<SILValue> args,
+         bool isNonThrowing, Optional<SILModuleConventions> moduleConventions,
+         SILFunction &F, SILOpenedArchetypesState &openedArchetypes,
+         const GenericSpecializationInformation *specializationInfo);
+
+public:
+  using MultipleValueInstructionTrailingObjects::totalSizeToAlloc;
+
+  SILValue getTokenResult() const {
+    return &getAllResultsBuffer().back();
+  }
+
+  SILInstructionResultArray getYieldedValues() const {
+    return getAllResultsBuffer().drop_back();
+  }
+
+  /// Returns true if the called coroutine has an error result but is not
+  /// actually throwing an error.
+  bool isNonThrowing() const {
+    return isNonThrowingApply();
+  }
+};
+
+inline BeginApplyInst *BeginApplyResult::getParent() {
+  auto *Parent = MultipleValueInstructionResult::getParent();
+  return cast<BeginApplyInst>(Parent);
+}
+inline bool BeginApplyResult::isTokenResult() const {
+  return getIndex() == getParent()->getNumResults() - 1;
+}
+
+/// AbortApplyInst - Unwind the full application of a yield_once coroutine.
+class AbortApplyInst
+    : public UnaryInstructionBase<SILInstructionKind::AbortApplyInst,
+                                  NonValueInstruction> {
+  friend SILBuilder;
+
+  AbortApplyInst(SILDebugLocation debugLoc, SILValue beginApplyToken)
+      : UnaryInstructionBase(debugLoc, beginApplyToken) {
+    assert(isa<BeginApplyResult>(beginApplyToken) &&
+           cast<BeginApplyResult>(beginApplyToken)->isTokenResult());
+  }
+
+public:
+  BeginApplyInst *getBeginApply() const {
+    return cast<BeginApplyResult>(getOperand())->getParent();
+  }
+};
+
+/// EndApplyInst - Resume the full application of a yield_once coroutine
+/// normally.
+class EndApplyInst
+    : public UnaryInstructionBase<SILInstructionKind::EndApplyInst,
+                                  NonValueInstruction> {
+  friend SILBuilder;
+
+  EndApplyInst(SILDebugLocation debugLoc, SILValue beginApplyToken)
+      : UnaryInstructionBase(debugLoc, beginApplyToken) {
+    assert(isa<BeginApplyResult>(beginApplyToken) &&
+           cast<BeginApplyResult>(beginApplyToken)->isTokenResult());
+  }
+
+public:
+  BeginApplyInst *getBeginApply() const {
+    return cast<BeginApplyResult>(getOperand())->getParent();
+  }
+};
+
 //===----------------------------------------------------------------------===//
 // Literal instructions.
 //===----------------------------------------------------------------------===//
@@ -6157,7 +6379,6 @@
       : NonValueInstruction(K, DebugLoc) {}
 
 public:
-
   using ConstSuccessorListTy = ArrayRef<SILSuccessor>;
   using SuccessorListTy = MutableArrayRef<SILSuccessor>;
 
@@ -6167,6 +6388,83 @@
     return const_cast<TermInst*>(this)->getSuccessors();
   }
 
+  using const_succ_iterator = ConstSuccessorListTy::const_iterator;
+  using succ_iterator = SuccessorListTy::iterator;
+
+  bool succ_empty() const { return getSuccessors().empty(); }
+  succ_iterator succ_begin() { return getSuccessors().begin(); }
+  succ_iterator succ_end() { return getSuccessors().end(); }
+  const_succ_iterator succ_begin() const { return getSuccessors().begin(); }
+  const_succ_iterator succ_end() const { return getSuccessors().end(); }
+
+  unsigned getNumSuccessors() const { return getSuccessors().size(); }
+
+  using succblock_iterator =
+      TransformIterator<SILSuccessor *,
+                        std::function<SILBasicBlock *(const SILSuccessor &)>>;
+  using const_succblock_iterator = TransformIterator<
+      const SILSuccessor *,
+      std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+  succblock_iterator succblock_begin() {
+    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformIterator(getSuccessors().begin(), F);
+  }
+  succblock_iterator succblock_end() {
+    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformIterator(getSuccessors().end(), F);
+  }
+  const_succblock_iterator succblock_begin() const {
+    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformIterator(getSuccessors().begin(), F);
+  }
+  const_succblock_iterator succblock_end() const {
+    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformIterator(getSuccessors().end(), F);
+  }
+
+  SILBasicBlock *getSingleSuccessorBlock() {
+    if (succ_empty() || std::next(succ_begin()) != succ_end())
+      return nullptr;
+    return *succ_begin();
+  }
+
+  const SILBasicBlock *getSingleSuccessorBlock() const {
+    return const_cast<TermInst *>(this)->getSingleSuccessorBlock();
+  }
+
+  /// \brief Returns true if \p BB is a successor of this block.
+  bool isSuccessorBlock(SILBasicBlock *BB) const {
+    auto Range = getSuccessorBlocks();
+    return any_of(Range, [&BB](const SILBasicBlock *SuccBB) -> bool {
+      return BB == SuccBB;
+    });
+  }
+
+  using SuccessorBlockListTy =
+      TransformRange<SuccessorListTy,
+                     std::function<SILBasicBlock *(const SILSuccessor &)>>;
+  using ConstSuccessorBlockListTy =
+      TransformRange<ConstSuccessorListTy, std::function<const SILBasicBlock *(
+                                               const SILSuccessor &)>>;
+
+  /// Return the range of SILBasicBlocks that are successors of this block.
+  SuccessorBlockListTy getSuccessorBlocks() {
+    using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformRange(getSuccessors(), F);
+  }
+
+  /// Return the range of SILBasicBlocks that are successors of this block.
+  ConstSuccessorBlockListTy getSuccessorBlocks() const {
+    using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+    FuncTy F(&SILSuccessor::getBB);
+    return makeTransformRange(getSuccessors(), F);
+  }
+
   DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(TermInst)
 
   bool isBranch() const { return !getSuccessors().empty(); }
@@ -6242,6 +6540,84 @@
   }
 };
 
+/// UnwindInst - Continue unwinding out of this function.  Currently this is
+/// only used in coroutines as the eventual terminator of the unwind edge
+/// out of a 'yield'.
+class UnwindInst
+  : public InstructionBase<SILInstructionKind::UnwindInst,
+                           TermInst> {
+  friend SILBuilder;
+
+  UnwindInst(SILDebugLocation loc)
+    : InstructionBase(loc) {}
+
+public:
+  SuccessorListTy getSuccessors() {
+    // No successors.
+    return SuccessorListTy();
+  }
+
+  ArrayRef<Operand> getAllOperands() const { return {}; }
+  MutableArrayRef<Operand> getAllOperands() { return {}; }
+};
+
+/// YieldInst - Yield control temporarily to the caller of this coroutine.
+///
+/// This is a terminator because the caller can abort the coroutine,
+/// e.g. if an error is thrown and an unwind is provoked.
+class YieldInst
+  : public InstructionBase<SILInstructionKind::YieldInst,
+                           TermInst> {
+  friend SILBuilder;
+
+  SILSuccessor DestBBs[2];
+
+  TailAllocatedOperandList<0> Operands;
+
+  YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+            SILBasicBlock *normalBB, SILBasicBlock *unwindBB);
+
+  static YieldInst *create(SILDebugLocation loc,
+                           ArrayRef<SILValue> yieldedValues,
+                           SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+                           SILFunction &F);
+
+public:
+  /// Return the normal resume destination of the yield, which is where the
+  /// coroutine resumes when the caller is ready to continue normally.
+  ///
+  /// This must be the unique predecessor edge of the given block.
+  ///
+  /// Control flow along every path from this block must either loop or
+  /// eventually terminate in a 'return', 'throw', or 'unreachable'
+  /// instruction.  In a yield_many coroutine, control is permitted to
+  /// first reach a 'yield' instruction; this is prohibited in a
+  /// yield_once coroutine.
+  SILBasicBlock *getResumeBB() const { return DestBBs[0]; }
+
+  /// Return the 'unwind' destination of the yield, which is where the
+  /// coroutine resumes when the caller is unconditionally aborting the
+  /// coroutine.
+  ///
+  /// This must be the unique predecessor edge of the given block.
+  ///
+  /// Control flow along every path from this block must either loop or
+  /// eventually terminate in an 'unwind' or 'unreachable' instruction.
+  /// It is not permitted to reach a 'yield' instruction.
+  SILBasicBlock *getUnwindBB() const { return DestBBs[1]; }
+
+  OperandValueArrayRef getYieldedValues() const {
+    return Operands.asValueArray();
+  }
+
+  ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
+  MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
+
+  SuccessorListTy getSuccessors() {
+    return DestBBs;
+  }
+};
+
 /// BranchInst - An unconditional branch.
 class BranchInst
     : public InstructionBase<SILInstructionKind::BranchInst,
@@ -6890,9 +7266,10 @@
 
 /// TryApplyInst - Represents the full application of a function that
 /// can produce an error.
-class TryApplyInst
+class TryApplyInst final
     : public InstructionBase<SILInstructionKind::TryApplyInst,
-                             ApplyInstBase<TryApplyInst, TryApplyInstBase>> {
+                             ApplyInstBase<TryApplyInst, TryApplyInstBase>>,
+      public llvm::TrailingObjects<TryApplyInst, Operand, Substitution> {
   friend SILBuilder;
 
   TryApplyInst(SILDebugLocation DebugLoc, SILValue callee,
@@ -6926,6 +7303,7 @@
   ApplySite(ApplyInst *inst) : Inst(inst) {}
   ApplySite(PartialApplyInst *inst) : Inst(inst) {}
   ApplySite(TryApplyInst *inst) : Inst(inst) {}
+  ApplySite(BeginApplyInst *inst) : Inst(inst) {}
 
   SILModule &getModule() const {
     return Inst->getModule();
@@ -6935,6 +7313,8 @@
     switch (node->getKind()) {
     case SILNodeKind::ApplyInst:
       return ApplySite(cast<ApplyInst>(node));
+    case SILNodeKind::BeginApplyInst:
+      return ApplySite(cast<BeginApplyInst>(node));
     case SILNodeKind::TryApplyInst:
       return ApplySite(cast<TryApplyInst>(node));
     case SILNodeKind::PartialApplyInst:
@@ -6956,11 +7336,13 @@
 
 #define FOREACH_IMPL_RETURN(OPERATION) do {                             \
     switch (Inst->getKind()) {                                          \
-    case SILInstructionKind::ApplyInst:                                          \
+    case SILInstructionKind::ApplyInst:                                 \
       return cast<ApplyInst>(Inst)->OPERATION;                          \
-    case SILInstructionKind::PartialApplyInst:                                   \
+    case SILInstructionKind::BeginApplyInst:                            \
+      return cast<BeginApplyInst>(Inst)->OPERATION;                     \
+    case SILInstructionKind::PartialApplyInst:                          \
       return cast<PartialApplyInst>(Inst)->OPERATION;                   \
-    case SILInstructionKind::TryApplyInst:                                       \
+    case SILInstructionKind::TryApplyInst:                              \
       return cast<TryApplyInst>(Inst)->OPERATION;                       \
     default:                                                            \
       llvm_unreachable("not an apply instruction!");                    \
@@ -7034,7 +7416,7 @@
   }
 
   /// The substitutions used to bind the generic arguments of this function.
-  MutableArrayRef<Substitution> getSubstitutions() const {
+  SubstitutionList getSubstitutions() const {
     FOREACH_IMPL_RETURN(getSubstitutions());
   }
 
@@ -7059,8 +7441,8 @@
   }
 
   /// The number of call arguments.
-  unsigned getNumCallArguments() const {
-    FOREACH_IMPL_RETURN(getNumCallArguments());
+  unsigned getNumArguments() const {
+    FOREACH_IMPL_RETURN(getNumArguments());
   }
 
   unsigned getOperandIndexOfFirstArgument() {
@@ -7078,6 +7460,8 @@
     switch (Inst->getKind()) {
     case SILInstructionKind::ApplyInst:
       return cast<ApplyInst>(Inst)->getArgumentsWithoutSelf();
+    case SILInstructionKind::BeginApplyInst:
+      return cast<BeginApplyInst>(Inst)->getArgumentsWithoutSelf();
     case SILInstructionKind::TryApplyInst:
       return cast<TryApplyInst>(Inst)->getArgumentsWithoutSelf();
     default:
@@ -7085,14 +7469,12 @@
     }
   }
 
-  /// Returns the number of arguments for this partial apply.
-  unsigned getNumArguments() const { return getArguments().size(); }
-
   // Get the callee argument index corresponding to the caller's first applied
   // argument. Returns 0 for full applies. May return > 0 for partial applies.
   unsigned getCalleeArgIndexOfFirstAppliedArg() const {
     switch (Inst->getKind()) {
     case SILInstructionKind::ApplyInst:
+    case SILInstructionKind::BeginApplyInst:
     case SILInstructionKind::TryApplyInst:
       return 0;
     case SILInstructionKind::PartialApplyInst:
@@ -7131,6 +7513,8 @@
     switch (Inst->getKind()) {
     case SILInstructionKind::ApplyInst:
       return cast<ApplyInst>(Inst)->hasSelfArgument();
+    case SILInstructionKind::BeginApplyInst:
+      return cast<BeginApplyInst>(Inst)->hasSelfArgument();
     case SILInstructionKind::TryApplyInst:
       return cast<TryApplyInst>(Inst)->hasSelfArgument();
     default:
@@ -7143,6 +7527,8 @@
     switch (Inst->getKind()) {
     case SILInstructionKind::ApplyInst:
       return cast<ApplyInst>(Inst)->getSelfArgument();
+    case SILInstructionKind::BeginApplyInst:
+      return cast<BeginApplyInst>(Inst)->getSelfArgument();
     case SILInstructionKind::TryApplyInst:
       return cast<TryApplyInst>(Inst)->getSelfArgument();
     default:
@@ -7155,6 +7541,8 @@
     switch (Inst->getKind()) {
     case SILInstructionKind::ApplyInst:
       return cast<ApplyInst>(Inst)->getSelfArgumentOperand();
+    case SILInstructionKind::BeginApplyInst:
+      return cast<BeginApplyInst>(Inst)->getSelfArgumentOperand();
     case SILInstructionKind::TryApplyInst:
       return cast<TryApplyInst>(Inst)->getSelfArgumentOperand();
     default:
@@ -7179,6 +7567,7 @@
 
   static bool classof(const SILInstruction *inst) {
     return (inst->getKind() == SILInstructionKind::ApplyInst ||
+            inst->getKind() == SILInstructionKind::BeginApplyInst ||
             inst->getKind() == SILInstructionKind::PartialApplyInst ||
             inst->getKind() == SILInstructionKind::TryApplyInst);
   }
@@ -7194,12 +7583,15 @@
     assert(classof(inst) && "not an apply instruction?");
   }
   FullApplySite(ApplyInst *inst) : ApplySite(inst) {}
+  FullApplySite(BeginApplyInst *inst) : ApplySite(inst) {}
   FullApplySite(TryApplyInst *inst) : ApplySite(inst) {}
 
   static FullApplySite isa(SILNode *node) {
     switch (node->getKind()) {
     case SILNodeKind::ApplyInst:
       return FullApplySite(cast<ApplyInst>(node));
+    case SILNodeKind::BeginApplyInst:
+      return FullApplySite(cast<BeginApplyInst>(node));
     case SILNodeKind::TryApplyInst:
       return FullApplySite(cast<TryApplyInst>(node));
     default:
@@ -7229,6 +7621,7 @@
 
   static bool classof(const SILInstruction *inst) {
     return (inst->getKind() == SILInstructionKind::ApplyInst ||
+            inst->getKind() == SILInstructionKind::BeginApplyInst ||
             inst->getKind() == SILInstructionKind::TryApplyInst);
   }
 };
@@ -7289,8 +7682,7 @@
     : public UnaryInstructionBase<SILInstructionKind::DestructureStructInst,
                                   MultipleValueInstruction>,
       public MultipleValueInstructionTrailingObjects<
-          SILInstructionKind::DestructureStructInst, DestructureStructInst,
-          DestructureStructResult> {
+          DestructureStructInst, DestructureStructResult> {
   friend TrailingObjects;
 
   DestructureStructInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
@@ -7338,8 +7730,7 @@
     : public UnaryInstructionBase<SILInstructionKind::DestructureTupleInst,
                                   MultipleValueInstruction>,
       public MultipleValueInstructionTrailingObjects<
-          SILInstructionKind::DestructureTupleInst, DestructureTupleInst,
-          DestructureTupleResult> {
+          DestructureTupleInst, DestructureTupleResult> {
   friend TrailingObjects;
 
   DestructureTupleInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 78a6318..6727455 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -215,9 +215,10 @@
   VALUE_RANGE(SILArgument, SILPHIArgument, SILFunctionArgument)
 
 ABSTRACT_VALUE(MultipleValueInstructionResult, ValueBase)
+  MULTIPLE_VALUE_INST_RESULT(BeginApplyResult, MultipleValueInstructionResult)
   MULTIPLE_VALUE_INST_RESULT(DestructureStructResult, MultipleValueInstructionResult)
   MULTIPLE_VALUE_INST_RESULT(DestructureTupleResult, MultipleValueInstructionResult)
-  VALUE_RANGE(MultipleValueInstructionResult, DestructureStructResult, DestructureTupleResult)
+  VALUE_RANGE(MultipleValueInstructionResult, BeginApplyResult, DestructureTupleResult)
 
 VALUE(SILUndef, ValueBase)
 
@@ -498,6 +499,10 @@
              TermInst, None, DoesNotRelease)
   TERMINATOR(ThrowInst, throw,
              TermInst, None, DoesNotRelease)
+  TERMINATOR(YieldInst, yield,
+             TermInst, MayHaveSideEffects, MayRelease)
+  TERMINATOR(UnwindInst, unwind,
+             TermInst, None, DoesNotRelease)
   TERMINATOR(TryApplyInst, try_apply,
              TermInst, MayHaveSideEffects, MayRelease)
   TERMINATOR(BranchInst, br,
@@ -628,6 +633,10 @@
                SILInstruction, MayHaveSideEffects, DoesNotRelease)
 NON_VALUE_INST(AllocGlobalInst, alloc_global,
                SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(EndApplyInst, end_apply,
+               SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(AbortApplyInst, abort_apply,
+               SILInstruction, MayHaveSideEffects, MayRelease)
 
 // Runtime failure
 // FIXME: Special MemBehavior for runtime failure?
@@ -637,11 +646,13 @@
 NODE_RANGE(NonValueInstruction, UnreachableInst, CondFailInst)
 
 ABSTRACT_INST(MultipleValueInstruction, SILInstruction)
+MULTIPLE_VALUE_INST(BeginApplyInst, begin_apply,
+                    SILInstruction, MayHaveSideEffects, MayRelease)
 MULTIPLE_VALUE_INST(DestructureStructInst, destructure_struct,
                     SILInstruction, None, DoesNotRelease)
 MULTIPLE_VALUE_INST(DestructureTupleInst, destructure_tuple,
                     SILInstruction, None, DoesNotRelease)
-INST_RANGE(MultipleValueInstruction, DestructureStructInst, DestructureTupleInst)
+INST_RANGE(MultipleValueInstruction, BeginApplyInst, DestructureTupleInst)
 
 NODE_RANGE(SILInstruction, AllocStackInst, DestructureTupleInst)
 NODE_RANGE(SILNode, SILPHIArgument, DestructureTupleInst)
diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h
index 5e1e7d5..5d2b135 100644
--- a/include/swift/SIL/SILType.h
+++ b/include/swift/SIL/SILType.h
@@ -539,6 +539,9 @@
   /// Get the standard exception type.
   static SILType getExceptionType(const ASTContext &C);
 
+  /// Get the SIL token type.
+  static SILType getSILTokenType(const ASTContext &C);
+
   //
   // Utilities for treating SILType as a pointer-like type.
   //
diff --git a/include/swift/SIL/SILVTableVisitor.h b/include/swift/SIL/SILVTableVisitor.h
index 1f06d80..54c07d9 100644
--- a/include/swift/SIL/SILVTableVisitor.h
+++ b/include/swift/SIL/SILVTableVisitor.h
@@ -43,8 +43,8 @@
   void maybeAddMethod(FuncDecl *fd) {
     assert(!fd->hasClangNode());
 
-    maybeAddEntry(SILDeclRef(fd, SILDeclRef::Kind::Func),
-                  fd->needsNewVTableEntry());
+    SILDeclRef constant(fd, SILDeclRef::Kind::Func);
+    maybeAddEntry(constant, constant.requiresNewVTableEntry());
   }
 
   void maybeAddConstructor(ConstructorDecl *cd) {
@@ -53,18 +53,14 @@
     // Required constructors (or overrides thereof) have their allocating entry
     // point in the vtable.
     if (cd->isRequired()) {
-      bool needsAllocatingEntry = cd->needsNewVTableEntry();
-      if (!needsAllocatingEntry)
-        if (auto *baseCD = cd->getOverriddenDecl())
-          needsAllocatingEntry = !baseCD->isRequired() || baseCD->hasClangNode();
-      maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Allocator),
-                    needsAllocatingEntry);
+      SILDeclRef constant(cd, SILDeclRef::Kind::Allocator);
+      maybeAddEntry(constant, constant.requiresNewVTableEntry());
     }
 
     // All constructors have their initializing constructor in the
     // vtable, which can be used by a convenience initializer.
-    maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Initializer),
-                  cd->needsNewVTableEntry());
+    SILDeclRef constant(cd, SILDeclRef::Kind::Initializer);
+    maybeAddEntry(constant, constant.requiresNewVTableEntry());
   }
 
   void maybeAddEntry(SILDeclRef declRef, bool needsNewEntry) {
diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h
index 0fe98f9..bba877c 100644
--- a/include/swift/SIL/SILWitnessTable.h
+++ b/include/swift/SIL/SILWitnessTable.h
@@ -169,7 +169,15 @@
       Method.Witness = nullptr;
     }
   };
-  
+
+  /// An entry for a conformance requirement that makes the requirement
+  /// conditional. These aren't public, but any witness thunks need to feed them
+  /// into the true witness functions.
+  struct ConditionalConformance {
+    CanType Requirement;
+    ProtocolConformanceRef Conformance;
+  };
+
 private:
   /// The module which contains the SILWitnessTable.
   SILModule &Mod;
@@ -188,6 +196,13 @@
   /// table has no witness entries or if it is a declaration.
   MutableArrayRef<Entry> Entries;
 
+  /// Any conditional conformances required for this witness table. These are
+  /// private to this conformance.
+  ///
+  /// (If other private entities are introduced this could/should be switched
+  /// into a private version of Entries.)
+  MutableArrayRef<ConditionalConformance> ConditionalConformances;
+
   /// Whether or not this witness table is a declaration. This is separate from
   /// whether or not entries is empty since you can have an empty witness table
   /// that is not a declaration.
@@ -198,10 +213,10 @@
   bool Serialized;
 
   /// Private constructor for making SILWitnessTable definitions.
-  SILWitnessTable(SILModule &M, SILLinkage Linkage,
-                  IsSerialized_t Serialized, StringRef Name,
-                  NormalProtocolConformance *Conformance,
-                  ArrayRef<Entry> entries);
+  SILWitnessTable(SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+                  StringRef Name, NormalProtocolConformance *Conformance,
+                  ArrayRef<Entry> entries,
+                  ArrayRef<ConditionalConformance> conditionalConformances);
 
   /// Private constructor for making SILWitnessTable declarations.
   SILWitnessTable(SILModule &M, SILLinkage Linkage, StringRef Name,
@@ -211,10 +226,10 @@
 
 public:
   /// Create a new SILWitnessTable definition with the given entries.
-  static SILWitnessTable *create(SILModule &M, SILLinkage Linkage,
-                                 IsSerialized_t Serialized,
-                                 NormalProtocolConformance *Conformance,
-                                 ArrayRef<Entry> entries);
+  static SILWitnessTable *
+  create(SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+         NormalProtocolConformance *Conformance, ArrayRef<Entry> entries,
+         ArrayRef<ConditionalConformance> conditionalConformances);
 
   /// Create a new SILWitnessTable declaration.
   static SILWitnessTable *create(SILModule &M, SILLinkage Linkage,
@@ -245,6 +260,11 @@
   /// Return all of the witness table entries.
   ArrayRef<Entry> getEntries() const { return Entries; }
 
+  /// Return all of the conditional conformances.
+  ArrayRef<ConditionalConformance> getConditionalConformances() const {
+    return ConditionalConformances;
+  }
+
   /// Clears methods in MethodWitness entries.
   /// \p predicate Returns true if the passed entry should be set to null.
   template <typename Predicate> void clearMethods_if(Predicate predicate) {
@@ -268,12 +288,28 @@
   void setLinkage(SILLinkage l) { Linkage = l; }
 
   /// Change a SILWitnessTable declaration into a SILWitnessTable definition.
-  void convertToDefinition(ArrayRef<Entry> newEntries,
-                           IsSerialized_t isSerialized);
+  void
+  convertToDefinition(ArrayRef<Entry> newEntries,
+                      ArrayRef<ConditionalConformance> conditionalConformances,
+                      IsSerialized_t isSerialized);
 
   // Whether a conformance should be serialized.
   static bool conformanceIsSerialized(ProtocolConformance *conformance);
 
+  /// Call \c fn on each (split apart) conditional requirement of \c conformance
+  /// that should appear in a witness table, i.e., conformance requirements that
+  /// need witness tables themselves.
+  ///
+  /// The \c unsigned argument to \c fn is a counter for the conditional
+  /// conformances, and should be used for indexing arrays of them.
+  ///
+  /// This acts like \c any_of: \c fn returning \c true will stop the
+  /// enumeration and \c enumerateWitnessTableConditionalConformances will
+  /// return \c true, while \c fn returning \c false will let it continue.
+  static bool enumerateWitnessTableConditionalConformances(
+      const ProtocolConformance *conformance,
+      llvm::function_ref<bool(unsigned, CanType, ProtocolDecl *)> fn);
+
   /// Print the witness table.
   void print(llvm::raw_ostream &OS, bool Verbose = false) const;
 
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index c0e63df..370b432 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -79,18 +79,22 @@
 }
 inline CanSILFunctionType
 adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep,
-                   Optional<ProtocolConformanceRef> witnessMethodConformance) {
+                   Optional<ProtocolConformanceRef> witnessMethodConformance,
+                   bool UseGuaranteedClosures) {
   if (t->getRepresentation() == rep) return t;
   auto extInfo = t->getExtInfo().withRepresentation(rep);
-
-  return adjustFunctionType(
-      t, extInfo, extInfo.hasContext() ? DefaultThickCalleeConvention
-                                       : ParameterConvention::Direct_Unowned,
-      witnessMethodConformance);
+  auto contextConvention = UseGuaranteedClosures
+                               ? ParameterConvention::Direct_Guaranteed
+                               : DefaultThickCalleeConvention;
+  return adjustFunctionType(t, extInfo,
+                            extInfo.hasContext()
+                                ? contextConvention
+                                : ParameterConvention::Direct_Unowned,
+                            witnessMethodConformance);
 }
 inline CanSILFunctionType
-adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep) {
-  return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone());
+adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep, bool UseGuaranteedClosures) {
+  return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone(), UseGuaranteedClosures);
 }
   
 
@@ -271,7 +275,11 @@
     return TypeLowering::LoweringStyle::Shallow;
   }
 
-  /// Emit a lowered 'release_value' operation.
+  //===--------------------------------------------------------------------===//
+  // DestroyValue
+  //===--------------------------------------------------------------------===//
+
+  /// Emit a lowered destroy value operation.
   ///
   /// This type must be loadable.
   virtual void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc,
@@ -286,7 +294,7 @@
     return emitDestroyValue(B, loc, value);
   }
 
-  /// Emit a lowered 'release_value' operation.
+  /// Emit a lowered destroy value operation.
   ///
   /// This type must be loadable.
   void emitLoweredDestroyValueShallow(SILBuilder &B, SILLocation loc,
@@ -294,7 +302,7 @@
     emitLoweredDestroyValue(B, loc, value, LoweringStyle::Shallow);
   }
 
-  /// Emit a lowered 'release_value' operation.
+  /// Emit a lowered destroy_value operation.
   ///
   /// This type must be loadable.
   void emitLoweredDestroyValueDeep(SILBuilder &B, SILLocation loc,
@@ -313,14 +321,18 @@
   virtual void emitDestroyValue(SILBuilder &B, SILLocation loc,
                                 SILValue value) const = 0;
 
-  /// Emit a lowered 'retain_value' operation.
+  //===--------------------------------------------------------------------===//
+  // CopyValue
+  //===--------------------------------------------------------------------===//
+
+  /// Emit a lowered copy value operation.
   ///
   /// This type must be loadable.
   virtual SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
                                         SILValue value,
                                         LoweringStyle style) const = 0;
 
-  /// Emit a lowered 'retain_value' operation.
+  /// Emit a lowered copy value operation.
   ///
   /// This type must be loadable.
   SILValue emitLoweredCopyValueShallow(SILBuilder &B, SILLocation loc,
@@ -328,7 +340,7 @@
     return emitLoweredCopyValue(B, loc, value, LoweringStyle::Shallow);
   }
 
-  /// Emit a lowered 'retain_value' operation.
+  /// Emit a lowered copy value operation.
   ///
   /// This type must be loadable.
   SILValue emitLoweredCopyValueDeep(SILBuilder &B, SILLocation loc,
diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h
index 0324d10..7e7af25 100644
--- a/include/swift/SILOptimizer/PassManager/PassManager.h
+++ b/include/swift/SILOptimizer/PassManager/PassManager.h
@@ -97,6 +97,9 @@
   /// same function.
   bool RestartPipeline = false;
 
+  /// If true, passes are also run for functions which have
+  /// OptimizationMode::NoOptimization.
+  bool isMandatoryPipeline = false;
 
   /// The IRGen SIL passes. These have to be dynamically added by IRGen.
   llvm::DenseMap<unsigned, SILTransform *> IRGenPasses;
@@ -104,12 +107,17 @@
 public:
   /// C'tor. It creates and registers all analysis passes, which are defined
   /// in Analysis.def.
-  SILPassManager(SILModule *M, llvm::StringRef Stage = "");
+  ///
+  /// If \p isMandatoryPipeline is true, passes are also run for functions
+  /// which have OptimizationMode::NoOptimization.
+  SILPassManager(SILModule *M, llvm::StringRef Stage = "",
+                 bool isMandatoryPipeline = false);
 
   /// C'tor. It creates an IRGen pass manager. Passes can query for the
   /// IRGenModule.
   SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
-                 llvm::StringRef Stage = "");
+                 llvm::StringRef Stage = "",
+                 bool isMandatoryPipeline = false);
 
   const SILOptions &getOptions() const;
 
diff --git a/include/swift/SILOptimizer/Utils/CFG.h b/include/swift/SILOptimizer/Utils/CFG.h
index 2ce5a80..44b781d 100644
--- a/include/swift/SILOptimizer/Utils/CFG.h
+++ b/include/swift/SILOptimizer/Utils/CFG.h
@@ -125,11 +125,52 @@
 bool splitAllCriticalEdges(SILFunction &F, bool OnlyNonCondBr,
                            DominanceInfo *DT, SILLoopInfo *LI);
 
+/// \brief Split all cond_br critical edges with non-trivial arguments in the
+/// function updating the dominator tree and loop information (if they are not
+/// set to null).
+///
+/// A current invariant of Ownership SIL is that cond_br can only have critical
+/// edges with non-trivial arguments. This simplifies computation.
+bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &F,
+                                                   DominanceInfo *DT,
+                                                   SILLoopInfo *LI);
+
 /// \brief Merge a basic block ending in a branch with its successor
 /// if possible. If dominance information or loop info is non null update it.
 /// Return true if block was merged.
 bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT,
                                   SILLoopInfo *LI);
 
+/// Given a list of \p UserBlocks and a list of \p DefBlocks, find a set of
+/// blocks that together with \p UserBlocks joint-postdominate \p
+/// DefBlocks. This is in a sense finding a set of blocks that "complete" \p
+/// UserBlocks with respect to \p DefBlocks. As an example, for the following
+/// CFG:
+///
+///       +-----+
+///       | Def |
+///       +-----+
+///       |     |
+///       v     v
+/// +-----+     +-----+
+/// |     |     | Use |
+/// +-----+     +-----+
+///
+/// the completion of the joint post-dominance set would be the empty
+/// block. This has two main uses:
+///
+/// 1. This can tell you the places where if you were to sink the Def one would
+/// need to insert "compensating code".
+///
+/// 2. It can be used to prove ownership correctness of @owned values by
+/// asserting that the set of UserBlocks has an empty completion, implying they
+/// jointly-post dominate the def.
+///
+/// *NOTE* This completion may not be unique.
+void completeJointPostDominanceSet(
+    ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+    llvm::SmallVectorImpl<SILBasicBlock *> &Completion);
+
 } // end namespace swift
+
 #endif
diff --git a/include/swift/SILOptimizer/Utils/SCCVisitor.h b/include/swift/SILOptimizer/Utils/SCCVisitor.h
index c0f2b4f..9ea03d2 100644
--- a/include/swift/SILOptimizer/Utils/SCCVisitor.h
+++ b/include/swift/SILOptimizer/Utils/SCCVisitor.h
@@ -133,8 +133,14 @@
     case TermKind::ReturnInst:
     case TermKind::SwitchValueInst:
     case TermKind::ThrowInst:
+    case TermKind::UnwindInst:
       llvm_unreachable("Did not expect terminator that does not have args!");
 
+    case TermKind::YieldInst:
+      for (auto &O : cast<YieldInst>(Term)->getAllOperands())
+        Operands.push_back(O.get());
+      return;
+
     case TermKind::TryApplyInst:
       for (auto &O : cast<TryApplyInst>(Term)->getAllOperands())
         Operands.push_back(O.get());
diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def
index 03f68a3..b772124 100644
--- a/include/swift/Serialization/DeclTypeRecordNodes.def
+++ b/include/swift/Serialization/DeclTypeRecordNodes.def
@@ -162,7 +162,7 @@
 TRAILING_INFO(GENERIC_PARAM)
 TRAILING_INFO(GENERIC_REQUIREMENT)
 TRAILING_INFO(LAYOUT_REQUIREMENT)
-OTHER(GENERIC_ENVIRONMENT, 244)
+OTHER(GENERIC_SIGNATURE, 244)
 OTHER(SIL_GENERIC_ENVIRONMENT, 245)
 
 OTHER(LOCAL_DISCRIMINATOR, 248)
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 8cc53e2..f701536 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -299,6 +299,9 @@
   /// Types referenced by this module.
   std::vector<Serialized<Type>> Types;
 
+  /// Generic signatures referenced by this module.
+  std::vector<Serialized<GenericSignature *>> GenericSignatures;
+
   /// Generic environments referenced by this module.
   std::vector<Serialized<GenericEnvironment *>> GenericEnvironments;
 
@@ -818,6 +821,9 @@
   /// is loaded instead.
   ModuleDecl *getModule(ArrayRef<Identifier> name);
 
+  /// Returns the generic signature for the given ID.
+  GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);
+
   /// Returns the generic signature or environment for the given ID,
   /// deserializing it if needed.
   ///
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 746988f..38fb3d1 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
 /// in source control, you should also update the comment to briefly
 /// 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.
-const uint16_t VERSION_MINOR = 380; // Last change: IUO decl attribute
+const uint16_t VERSION_MINOR = 385; // Last change: Optimization attribute
 
 using DeclIDField = BCFixed<31>;
 
@@ -77,6 +77,11 @@
 using NormalConformanceID = DeclID;
 using NormalConformanceIDField = DeclIDField;
 
+// GenericSignatureID must be the same as DeclID because it is stored in the
+// same way.
+using GenericSignatureID = DeclID;
+using GenericSignatureIDField = DeclIDField;
+
 // GenericEnvironmentID must be the same as DeclID because it is stored in the
 // same way.
 using GenericEnvironmentID = DeclID;
@@ -156,6 +161,15 @@
 
 // These IDs must \em not be renumbered or reordered without incrementing
 // VERSION_MAJOR.
+enum class SILCoroutineKind : uint8_t {
+  None = 0,
+  YieldOnce = 1,
+  YieldMany = 2,
+};
+using SILCoroutineKindField = BCFixed<2>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
 enum OperatorKind : uint8_t {
   Infix = 0,
   Prefix,
@@ -729,25 +743,25 @@
     TypeIDField,         // output
     FunctionTypeRepresentationField, // representation
     BCFixed<1>,          // throws?
-    BCArray<TypeIDField> // generic parameters
-                         // followed by requirements
+    GenericSignatureIDField // generic signture
   >;
 
   using SILFunctionTypeLayout = BCRecordLayout<
     SIL_FUNCTION_TYPE,
+    SILCoroutineKindField, // coroutine kind
     ParameterConventionField, // callee convention
     SILFunctionTypeRepresentationField, // representation
     BCFixed<1>,            // pseudogeneric?
     BCFixed<1>,            // noescape?
     BCFixed<1>,            // error result?
     BCFixed<30>,           // number of parameters
+    BCFixed<30>,           // number of yields
     BCFixed<30>,           // number of results
+    GenericSignatureIDField, // generic signature
     BCArray<TypeIDField>   // parameter types/conventions, alternating
                            // followed by result types/conventions, alternating
                            // followed by error result type/convention
-                           // followed by generic parameter types
     // Optionally a protocol conformance (for witness_methods)
-    // Trailed by its generic requirements, if any.
   >;
   
   using SILBlockStorageTypeLayout = BCRecordLayout<
@@ -757,10 +771,9 @@
 
   using SILLayoutLayout = BCRecordLayout<
     SIL_LAYOUT,
+    GenericSignatureIDField,    // generic signature
     BCFixed<31>,                // number of fields
     BCArray<TypeIDWithBitField> // field types with mutability
-                                // followed by generic parameters
-                                // trailed by generic requirements, if any
   >;
 
   using SILBoxTypeLayout = BCRecordLayout<
@@ -1154,9 +1167,9 @@
     DeclIDField // Typealias
   >;
 
-  using GenericEnvironmentLayout = BCRecordLayout<
-    GENERIC_ENVIRONMENT,
-    BCArray<TypeIDField>         // sugared interface types
+  using GenericSignatureLayout = BCRecordLayout<
+    GENERIC_SIGNATURE,
+    BCArray<TypeIDField>         // generic parameter types
   >;
 
   using SILGenericEnvironmentLayout = BCRecordLayout<
@@ -1271,8 +1284,8 @@
   using XRefExtensionPathPieceLayout = BCRecordLayout<
     XREF_EXTENSION_PATH_PIECE,
     ModuleIDField,       // module ID
-    BCArray<TypeIDField> // for a constrained extension, the type parameters
-    // for a constrained extension, requirements follow
+    GenericSignatureIDField  // for a constrained extension,
+                             // the generic signature
   >;
 
   using XRefOperatorOrAccessorPathPieceLayout = BCRecordLayout<
@@ -1388,6 +1401,11 @@
     BCFixed<2>  // inline value
   >;
 
+  using OptimizeDeclAttrLayout = BCRecordLayout<
+    Optimize_DECL_ATTR,
+    BCFixed<2>  // optimize value
+  >;
+
   // Encodes a VersionTuple:
   //
   //  Major
@@ -1524,7 +1542,8 @@
     NESTED_TYPE_DECLS,
     DECL_MEMBER_NAMES,
 
-    LastRecordKind = DECL_MEMBER_NAMES,
+    GENERIC_SIGNATURE_OFFSETS,
+    LastRecordKind = GENERIC_SIGNATURE_OFFSETS,
   };
   
   constexpr const unsigned RecordIDFieldWidth = 5;
diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h
index 0978e16..13db711 100644
--- a/include/swift/Serialization/SerializedModuleLoader.h
+++ b/include/swift/Serialization/SerializedModuleLoader.h
@@ -195,6 +195,10 @@
 
   virtual const clang::Module *getUnderlyingClangModule() const override;
 
+  virtual bool getAllGenericSignatures(
+                   SmallVectorImpl<GenericSignature*> &genericSignatures)
+                override;
+
   static bool classof(const FileUnit *file) {
     return file->getKind() == FileUnitKind::SerializedAST;
   }
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index e79e188..e52f0ba 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -212,6 +212,8 @@
             const SourcePresence Presence)
       : Kind(Kind), Layout(Layout), Presence(Presence) {}
 
+  virtual ~RawSyntax() = default;
+
   /// Returns a raw syntax node of the given Kind, specified Layout,
   /// and source presence.
   static RC<RawSyntax> make(const SyntaxKind Kind, const LayoutList Layout,
diff --git a/include/swift/Syntax/SyntaxFactory.h.gyb b/include/swift/Syntax/SyntaxFactory.h.gyb
index 26f4879..e9f7c09 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -54,8 +54,16 @@
   static Optional<Syntax>
   createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements);
 
+  /// Count the number of children for a given syntax node kind,
+  /// returning a pair of mininum and maximum count of children. The gap
+  /// between these two numbers is the number of optional children.
+  static std::pair<unsigned, unsigned> countChildren(SyntaxKind Kind);
+
   static SyntaxKind getUnknownKind(SyntaxKind Kind);
 
+  static Syntax
+  makeBlankCollectionSyntax(SyntaxKind Kind);
+
 % for node in SYNTAX_NODES:
 %   if node.children:
 %     child_params = []
diff --git a/include/swift/Syntax/SyntaxParsingContext.h b/include/swift/Syntax/SyntaxParsingContext.h
index 002f9b0..9eba962 100644
--- a/include/swift/Syntax/SyntaxParsingContext.h
+++ b/include/swift/Syntax/SyntaxParsingContext.h
@@ -37,6 +37,12 @@
   /// Start and end location of this syntax node.
   SourceRange SyntaxRange;
 
+  /// This location must be valid if this node is an implicit node, e.g.
+  /// an empty statement list collection.
+  /// This location indicates the implicit node should appear before the token
+  /// on the location.
+  SourceLoc BeforeLoc;
+
   /// The raw node.
   RC<RawSyntax> RawNode;
   RawSyntaxInfo(RC<RawSyntax> RawNode): RawNode(RawNode) {}
@@ -57,6 +63,10 @@
     return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
   }
   void brigeWithContext(SyntaxContextKind Kind);
+  void setBeforeLoc(SourceLoc Loc) {
+    assert(isImplicit());
+    BeforeLoc = Loc;
+  }
 };
 
 enum class SyntaxParsingContextKind: uint8_t {
@@ -75,17 +85,15 @@
   ContextInfo &ContextData;
   const Token &Tok;
 
-  // Add a token syntax at the given source location to the context; this
-  // token node can be used to build more complex syntax nodes in later call
-  // back.
-  virtual void addTokenSyntax(SourceLoc Loc) = 0;
-
   // Get the context kind.
   virtual SyntaxParsingContextKind getKind() = 0;
 
   // Create a syntax node of the given kind.
-  virtual void makeNode(SyntaxKind Kind) = 0;
+  virtual void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) = 0;
   virtual ~SyntaxParsingContext();
+  virtual void setSyntaxKind(SyntaxKind Kind) = 0;
+  virtual void setContextKind(SyntaxContextKind CKind) = 0;
+  virtual void finalize() = 0;
 
   // Disable the building of syntax tree in the current context.
   void disable();
@@ -100,8 +108,10 @@
   SyntaxParsingContextRoot(SourceFile &File, unsigned BufferID, Token &Tok):
     SyntaxParsingContext(File, BufferID, Tok), File(File) {}
   ~SyntaxParsingContextRoot();
-  void addTokenSyntax(SourceLoc Loc) override {};
-  void makeNode(SyntaxKind Kind) override {};
+  void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override {};
+  void setSyntaxKind(SyntaxKind Kind) override {};
+  void setContextKind(SyntaxContextKind CKind) override {};
+  void finalize() override {};
   SyntaxParsingContextKind getKind() override {
     return SyntaxParsingContextKind::Root;
   };
@@ -114,12 +124,13 @@
 class SyntaxParsingContextChild: public SyntaxParsingContext {
   SyntaxParsingContext *Parent;
   SyntaxParsingContext *&ContextHolder;
-  Optional<SyntaxContextKind> Kind;
+  Optional<SyntaxContextKind> ContextKind;
   Optional<SyntaxKind> KnownSyntax;
   void makeNodeWhole(SyntaxKind Kind);
   SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
                             Optional<SyntaxContextKind> Kind,
                             Optional<SyntaxKind> KnownSyntax);
+  bool isTopOfContextStack() const { return this == ContextHolder; }
 public:
   SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
     SyntaxContextKind Kind): SyntaxParsingContextChild(ContextHolder,
@@ -129,10 +140,15 @@
     SyntaxKind KnownSyntax): SyntaxParsingContextChild(ContextHolder,
                              None, KnownSyntax) {};
 
+  SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
+                            bool Disable = false);
+
   ~SyntaxParsingContextChild();
-  void makeNode(SyntaxKind Kind) override;
-  void addTokenSyntax(SourceLoc Loc) override;
+  void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override;
+  void finalize() override;
   SyntaxParsingContext* getParent() { return Parent; }
+  void setSyntaxKind(SyntaxKind SKind) override;
+  void setContextKind(SyntaxContextKind CKind) override;
   SyntaxParsingContextRoot &getRoot();
   SyntaxParsingContextKind getKind() override {
     return SyntaxParsingContextKind::Child;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 314321f..cd854df 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -266,16 +266,6 @@
   /// The keys are the generic signature builders in \c GenericSignatureBuilders.
   llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
     CanonicalGenericEnvironments;
-
-  /// The set of property names that show up in the defining module of a
-  /// class.
-  llvm::DenseMap<std::pair<const ClassDecl *, char>,
-                 std::unique_ptr<InheritedNameSet>> AllProperties;
-
-  /// The set of property names that show up in the defining module of
-  /// an Objective-C class.
-  llvm::DenseMap<std::pair<const clang::ObjCInterfaceDecl *, char>,
-                 std::unique_ptr<InheritedNameSet>> AllPropertiesObjC;
   
   /// The single-parameter generic signature with no constraints, <T>.
   CanGenericSignature SingleGenericParameterSignature;
@@ -471,6 +461,8 @@
                         BuiltinRawPointerType(*this)),
     TheUnsafeValueBufferType(new (*this, AllocationArena::Permanent)
                                BuiltinUnsafeValueBufferType(*this)),
+    TheSILTokenType(new (*this, AllocationArena::Permanent)
+                      SILTokenType(*this)),
     TheIEEE32Type(new (*this, AllocationArena::Permanent)
                     BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
     TheIEEE64Type(new (*this, AllocationArena::Permanent)
@@ -3787,16 +3779,22 @@
 void SILFunctionType::Profile(llvm::FoldingSetNodeID &id,
                               GenericSignature *genericParams,
                               ExtInfo info,
+                              SILCoroutineKind coroutineKind,
                               ParameterConvention calleeConvention,
                               ArrayRef<SILParameterInfo> params,
+                              ArrayRef<SILYieldInfo> yields,
                               ArrayRef<SILResultInfo> results,
                               Optional<SILResultInfo> errorResult) {
   id.AddPointer(genericParams);
   id.AddInteger(info.getFuncAttrKey());
+  id.AddInteger(unsigned(coroutineKind));
   id.AddInteger(unsigned(calleeConvention));
   id.AddInteger(params.size());
   for (auto param : params)
     param.profile(id);
+  id.AddInteger(yields.size());
+  for (auto yield : yields)
+    yield.profile(id);
   id.AddInteger(results.size());
   for (auto result : results)
     result.profile(id);
@@ -3806,32 +3804,47 @@
   if (errorResult) errorResult->profile(id);
 }
 
-SILFunctionType::SILFunctionType(
-    GenericSignature *genericSig, ExtInfo ext,
-    ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
-    ArrayRef<SILResultInfo> normalResults, Optional<SILResultInfo> errorResult,
-    const ASTContext &ctx, RecursiveTypeProperties properties,
-    Optional<ProtocolConformanceRef> witnessMethodConformance)
-    : TypeBase(TypeKind::SILFunction, &ctx, properties), GenericSig(genericSig),
+SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+                                 SILCoroutineKind coroutineKind,
+                                 ParameterConvention calleeConvention,
+                                 ArrayRef<SILParameterInfo> params,
+                                 ArrayRef<SILYieldInfo> yields,
+                                 ArrayRef<SILResultInfo> normalResults,
+                                 Optional<SILResultInfo> errorResult,
+                                 const ASTContext &ctx,
+                                 RecursiveTypeProperties properties,
+                      Optional<ProtocolConformanceRef> witnessMethodConformance)
+    : TypeBase(TypeKind::SILFunction, &ctx, properties),
+      GenericSig(genericSig),
       WitnessMethodConformance(witnessMethodConformance) {
 
   SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
   SILFunctionTypeBits.ExtInfo = ext.Bits;
+  SILFunctionTypeBits.CoroutineKind = unsigned(coroutineKind);
   NumParameters = params.size();
-  NumResults = normalResults.size();
-  NumIndirectFormalResults =
+  if (coroutineKind == SILCoroutineKind::None) {
+    assert(yields.empty());
+    NumAnyResults = normalResults.size();
+    NumAnyIndirectFormalResults =
       std::count_if(normalResults.begin(), normalResults.end(),
                     [](const SILResultInfo &resultInfo) {
                       return resultInfo.isFormalIndirect();
                     });
+    memcpy(getMutableResults().data(), normalResults.data(),
+           normalResults.size() * sizeof(SILResultInfo));
+  } else {
+    assert(normalResults.empty());    
+    NumAnyResults = yields.size();
+    NumAnyIndirectFormalResults = 0; // unused
+    memcpy(getMutableYields().data(), yields.data(),
+           yields.size() * sizeof(SILYieldInfo));
+  }
 
   assert(!isIndirectFormalParameter(calleeConvention));
   SILFunctionTypeBits.CalleeConvention = unsigned(calleeConvention);
 
   memcpy(getMutableParameters().data(), params.data(),
          params.size() * sizeof(SILParameterInfo));
-  memcpy(getMutableResults().data(), normalResults.data(),
-         normalResults.size() * sizeof(SILResultInfo));
   if (errorResult)
     getMutableErrorResult() = *errorResult;
 
@@ -3868,6 +3881,13 @@
       assert(!result.getType()->hasArchetype()
              && "interface type of result should not contain context archetypes");
     }
+    for (auto yield : getYields()) {
+      (void)yield;
+      assert(!yield.getType()->hasError()
+             && "interface type of yield should not contain error types");
+      assert(!yield.getType()->hasArchetype()
+             && "interface type of yield should not contain context archetypes");
+    }
     if (hasErrorResult()) {
       assert(!getErrorResult().getType()->hasError()
              && "interface type of result should not contain error types");
@@ -3892,14 +3912,22 @@
   return CanSILBlockStorageType(storageTy);
 }
 
-CanSILFunctionType SILFunctionType::get(
-    GenericSignature *genericSig, ExtInfo ext, ParameterConvention callee,
-    ArrayRef<SILParameterInfo> params, ArrayRef<SILResultInfo> normalResults,
-    Optional<SILResultInfo> errorResult, const ASTContext &ctx,
-    Optional<ProtocolConformanceRef> witnessMethodConformance) {
+CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
+                                        ExtInfo ext,
+                                        SILCoroutineKind coroutineKind,
+                                        ParameterConvention callee,
+                                        ArrayRef<SILParameterInfo> params,
+                                        ArrayRef<SILYieldInfo> yields,
+                                        ArrayRef<SILResultInfo> normalResults,
+                                        Optional<SILResultInfo> errorResult,
+                                        const ASTContext &ctx,
+                    Optional<ProtocolConformanceRef> witnessMethodConformance) {
+  assert(coroutineKind == SILCoroutineKind::None || normalResults.empty());
+  assert(coroutineKind != SILCoroutineKind::None || yields.empty());
+
   llvm::FoldingSetNodeID id;
-  SILFunctionType::Profile(id, genericSig, ext, callee, params, normalResults,
-                           errorResult);
+  SILFunctionType::Profile(id, genericSig, ext, coroutineKind, callee,
+                           params, yields, normalResults, errorResult);
 
   // Do we already have this generic function type?
   void *insertPos;
@@ -3912,6 +3940,7 @@
   // Allocate storage for the object.
   size_t bytes = sizeof(SILFunctionType)
                  + sizeof(SILParameterInfo) * params.size()
+                 + sizeof(SILYieldInfo) * yields.size()
                  + sizeof(SILResultInfo) * normalResults.size()
                  + (errorResult ? sizeof(SILResultInfo) : 0)
                  + (normalResults.size() > 1 ? sizeof(CanType) * 2 : 0);
@@ -3922,6 +3951,8 @@
                 "revisit this if you add new recursive type properties");
   for (auto &param : params)
     properties |= param.getType()->getRecursiveProperties();
+  for (auto &yield : yields)
+    properties |= yield.getType()->getRecursiveProperties();
   for (auto &result : normalResults)
     properties |= result.getType()->getRecursiveProperties();
   if (errorResult)
@@ -3934,9 +3965,10 @@
     properties.removeHasDependentMember();
   }
 
-  auto fnType = new (mem)
-      SILFunctionType(genericSig, ext, callee, params, normalResults,
-                      errorResult, ctx, properties, witnessMethodConformance);
+  auto fnType =
+      new (mem) SILFunctionType(genericSig, ext, coroutineKind, callee,
+                                params, yields, normalResults, errorResult,
+                                ctx, properties, witnessMethodConformance);
   ctx.Impl.SILFunctionTypes.InsertNode(fnType, insertPos);
   return CanSILFunctionType(fnType);
 }
@@ -4673,129 +4705,6 @@
   return Type();
 }
 
-const InheritedNameSet *ASTContext::getAllPropertyNames(ClassDecl *classDecl,
-                                                        bool forInstance) {
-  // If this class was defined in Objective-C, perform the lookup based on
-  // the Objective-C class.
-  if (auto objcClass = dyn_cast_or_null<clang::ObjCInterfaceDecl>(
-                         classDecl->getClangDecl())) {
-    return getAllPropertyNames(
-             const_cast<clang::ObjCInterfaceDecl *>(objcClass),
-             forInstance);
-  }
-
-  // If we already have this information, return it.
-  auto known = Impl.AllProperties.find({classDecl, forInstance});
-  if (known != Impl.AllProperties.end()) return known->second.get();
-
-  // Otherwise, get information from our superclass first.
-  if (auto resolver = getLazyResolver())
-    resolver->resolveSuperclass(classDecl);
-
-  const InheritedNameSet *parentSet = nullptr;
-  if (auto superclass = classDecl->getSuperclass()) {
-    if (auto superclassDecl = superclass->getClassOrBoundGenericClass()) {
-      parentSet = getAllPropertyNames(superclassDecl, forInstance);
-    }
-  }
-
-  // Create the set of properties.
-  known = Impl.AllProperties.insert(
-            { std::pair<const ClassDecl *, char>(classDecl, forInstance),
-              llvm::make_unique<InheritedNameSet>(parentSet) }).first;
-
-  // Local function to add properties from the given set.
-  auto addProperties = [&](DeclRange members) {
-    for (auto member : members) {
-      auto var = dyn_cast<VarDecl>(member);
-      if (!var || var->getName().empty()) continue;
-      if (var->isInstanceMember() != forInstance) continue;
-
-      known->second->add(var->getName().str());
-    }
-  };
-
-  // Collect property names from the class.
-  addProperties(classDecl->getMembers());
-
-  // Collect property names from all extensions in the same module as the class.
-  auto module = classDecl->getParentModule();
-  for (auto ext : classDecl->getExtensions()) {
-    if (ext->getParentModule() != module) continue;
-    addProperties(ext->getMembers());
-  }
-
-  return known->second.get();
-}
-
-const InheritedNameSet *ASTContext::getAllPropertyNames(
-                          clang::ObjCInterfaceDecl *classDecl,
-                          bool forInstance) {
-  classDecl = classDecl->getCanonicalDecl();
-
-  // If we already have this information, return it.
-  auto known = Impl.AllPropertiesObjC.find({classDecl, forInstance});
-  if (known != Impl.AllPropertiesObjC.end()) return known->second.get();
-
-  // Otherwise, get information from our superclass first.
-  const InheritedNameSet *parentSet = nullptr;
-  if (auto superclassDecl = classDecl->getSuperClass()) {
-    parentSet = getAllPropertyNames(superclassDecl, forInstance);
-  }
-
-  // Create the set of properties.
-  known = Impl.AllPropertiesObjC.insert(
-            { std::pair<const clang::ObjCInterfaceDecl *, char>(classDecl,
-                                                                forInstance),
-              llvm::make_unique<InheritedNameSet>(parentSet) }).first;
-
-  // Local function to add properties from the given set.
-  auto addProperties = [&](clang::DeclContext::decl_range members) {
-    for (auto member : members) {
-      // Add Objective-C property names.
-      if (auto property = dyn_cast<clang::ObjCPropertyDecl>(member)) {
-        if (forInstance)
-          known->second->add(property->getName());
-        continue;
-      }
-
-      // Add no-parameter, non-void method names.
-      if (auto method = dyn_cast<clang::ObjCMethodDecl>(member)) {
-        if (method->getSelector().isUnarySelector() &&
-            !method->getReturnType()->isVoidType() &&
-            !method->hasRelatedResultType() &&
-            method->isInstanceMethod() == forInstance) {
-          known->second->add(method->getSelector().getNameForSlot(0));
-          continue;
-        }
-      }
-    }
-  };
-
-  // Dig out the class definition.
-  auto classDef = classDecl->getDefinition();
-  if (!classDef) return known->second.get();
-
-  // Collect property names from the class definition.
-  addProperties(classDef->decls());
-
-  // Dig out the module that owns the class definition.
-  auto module = classDef->getImportedOwningModule();
-  if (module) module = module->getTopLevelModule();
-
-  // Collect property names from all categories and extensions in the same
-  // module as the class.
-  for (auto category : classDef->known_categories()) {
-    auto categoryModule = category->getImportedOwningModule();
-    if (categoryModule) categoryModule = categoryModule->getTopLevelModule();
-    if (module != categoryModule) continue;
-
-    addProperties(category->decls());
-  }
-
-  return known->second.get();
-}
-
 CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
   if (auto theSig = Impl.SingleGenericParameterSignature)
     return theSig;
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index c72c90d..620b828 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2926,6 +2926,7 @@
     TRIVIAL_TYPE_PRINTER(BuiltinBridgeObject, builtin_bridge_object)
     TRIVIAL_TYPE_PRINTER(BuiltinUnknownObject, builtin_unknown_object)
     TRIVIAL_TYPE_PRINTER(BuiltinUnsafeValueBuffer, builtin_unsafe_value_buffer)
+    TRIVIAL_TYPE_PRINTER(SILToken, sil_token)
 
     void visitBuiltinVectorType(BuiltinVectorType *T, StringRef label) {
       printCommon(label, "builtin_vector_type");
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 116613a..6cc18c4 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -527,6 +527,7 @@
   switch (SKind) {
     case SymbolKind::Default: return;
     case SymbolKind::DynamicThunk: return appendOperator("TD");
+    case SymbolKind::SwiftDispatchThunk: return appendOperator("Tj");
     case SymbolKind::SwiftAsObjCThunk: return appendOperator("To");
     case SymbolKind::ObjCAsSwiftThunk: return appendOperator("TO");
     case SymbolKind::DirectMethodReferenceThunk: return appendOperator("Td");
@@ -704,6 +705,8 @@
       return appendOperator("BO");
     case TypeKind::BuiltinUnsafeValueBuffer:
       return appendOperator("BB");
+    case TypeKind::SILToken:
+      return appendOperator("Bt");
     case TypeKind::BuiltinVector:
       appendType(cast<BuiltinVectorType>(tybase)->getElementType());
       return appendOperator("Bv",
diff --git a/lib/AST/ASTNode.cpp b/lib/AST/ASTNode.cpp
index e5f70b9..f182f01 100644
--- a/lib/AST/ASTNode.cpp
+++ b/lib/AST/ASTNode.cpp
@@ -76,16 +76,6 @@
   else
     llvm_unreachable("unsupported AST node");
 }
-void ASTNode::walk(SourceEntityWalker &Walker) {
-  if (auto *E = this->dyn_cast<Expr*>())
-    Walker.walk(E);
-  else if (auto *S = this->dyn_cast<Stmt*>())
-    Walker.walk(S);
-  else if (auto *D = this->dyn_cast<Decl*>())
-    Walker.walk(D);
-  else
-    llvm_unreachable("unsupported AST node");
-}
 
 #define FUNC(T)                                                               \
 bool ASTNode::is##T(T##Kind Kind) const {                                     \
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 6a8cebf..02de748 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -3255,6 +3255,10 @@
     }
   }
 
+  void visitSILTokenType(SILTokenType *T) {
+    Printer << "Builtin.SILToken";
+  }
+
   void visitNameAliasType(NameAliasType *T) {
     if (Options.PrintForSIL || Options.PrintNameAliasUnderlyingType) {
       visit(T->getSinglyDesugaredType());
@@ -3630,6 +3634,20 @@
     Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
   }
 
+  void printSILCoroutineKind(SILCoroutineKind kind) {
+    switch (kind) {
+    case SILCoroutineKind::None:
+      return;
+    case SILCoroutineKind::YieldOnce:
+      Printer << "@yield_once ";
+      return;
+    case SILCoroutineKind::YieldMany:
+      Printer << "@yield_many ";
+      return;
+    }
+    llvm_unreachable("bad convention");
+  }
+
   void printCalleeConvention(ParameterConvention conv) {
     switch (conv) {
     case ParameterConvention::Direct_Unowned:
@@ -3651,6 +3669,7 @@
   }
 
   void visitSILFunctionType(SILFunctionType *T) {
+    printSILCoroutineKind(T->getCoroutineKind());
     printFunctionExtInfo(T->getExtInfo(),
                          T->getWitnessMethodConformanceOrNone());
     printCalleeConvention(T->getCalleeConvention());
@@ -3669,11 +3688,19 @@
     }
     Printer << ") -> ";
 
-    unsigned totalResults = T->getNumResults() + unsigned(T->hasErrorResult());
+    unsigned totalResults =
+      T->getNumYields() + T->getNumResults() + unsigned(T->hasErrorResult());
 
     if (totalResults != 1) Printer << "(";
 
     first = true;
+
+    for (auto yield : T->getYields()) {
+      Printer.printSeparator(first, ", ");
+      Printer << "@yields ";
+      yield.print(Printer, Options);
+    }
+
     for (auto result : T->getResults()) {
       Printer.printSeparator(first, ", ");
       result.print(Printer, Options);
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index d723d43..5456345 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1980,6 +1980,108 @@
         abort();
       }
     }
+  
+    void verifyChecked(KeyPathApplicationExpr *E) {
+      PrettyStackTraceExpr debugStack(
+        Ctx, "verifying KeyPathApplicationExpr", E);
+      
+      auto baseTy = E->getBase()->getType();
+      auto keyPathTy = E->getKeyPath()->getType();
+      auto resultTy = E->getType();
+      
+      if (auto nom = keyPathTy->getAs<NominalType>()) {
+        if (nom->getDecl() == Ctx.getAnyKeyPathDecl()) {
+          // AnyKeyPath application is <T> rvalue T -> rvalue Any?
+          if (baseTy->is<LValueType>()) {
+            Out << "AnyKeyPath application base is not an rvalue\n";
+            abort();
+          }
+          auto resultObjTy = resultTy->getOptionalObjectType();
+          if (!resultObjTy || !resultObjTy->isAny()) {
+            Out << "AnyKeyPath application result must be Any?\n";
+            abort();
+          }
+          return;
+        }
+      } else if (auto bgt = keyPathTy->getAs<BoundGenericType>()) {
+        if (bgt->getDecl() == Ctx.getPartialKeyPathDecl()) {
+          // PartialKeyPath<T> application is rvalue T -> rvalue Any
+          if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+            Out << "PartialKeyPath application base doesn't match type\n";
+            abort();
+          }
+          if (!resultTy->isAny()) {
+            Out << "PartialKeyPath application result must be Any?\n";
+            abort();
+          }
+          return;
+        } else if (bgt->getDecl() == Ctx.getKeyPathDecl()) {
+          // KeyPath<T, U> application is rvalue T -> rvalue U
+          if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+            Out << "KeyPath application base doesn't match type\n";
+            abort();
+          }
+          if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+            Out << "KeyPath application result doesn't match type\n";
+            abort();
+          }
+          return;
+        } else if (bgt->getDecl() == Ctx.getWritableKeyPathDecl()) {
+          // WritableKeyPath<T, U> application is
+          //    lvalue T -> lvalue U
+          // or rvalue T -> rvalue U
+          if (baseTy->is<LValueType>()) {
+            if (!resultTy->is<LValueType>()) {
+              Out << "WritableKeyPath base and result don't match lvalue-ness\n";
+              abort();
+            }
+            baseTy = baseTy->getRValueType();
+            resultTy = resultTy->getRValueType();
+          }
+          
+          if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+            Out << "WritableKeyPath application base doesn't match type\n";
+            abort();
+          }
+          if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+            Out << "WritableKeyPath application result doesn't match type\n";
+            abort();
+          }
+          return;
+        } else if (bgt->getDecl() == Ctx.getReferenceWritableKeyPathDecl()) {
+          // ReferenceWritableKeyPath<T, U> application is
+          //    rvalue T -> lvalue U
+          // or lvalue T -> lvalue U
+          // or rvalue T -> rvalue U
+          if (baseTy->is<LValueType>()) {
+            if (!resultTy->is<LValueType>()) {
+              Out << "ReferenceWritableKeyPath base and result don't "
+                     "match lvalue-ness\n";
+              abort();
+            }
+            baseTy = baseTy->getRValueType();
+            resultTy = resultTy->getRValueType();
+          } else {
+            resultTy = resultTy->getRValueType();
+          }
+
+          if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+            Out << "ReferenceWritableKeyPath application base doesn't "
+                   "match type\n";
+            abort();
+          }
+          if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+            Out << "ReferenceWritableKeyPath application result doesn't "
+                   "match type\n";
+            abort();
+          }
+          return;
+        }
+      }
+      
+      Out << "invalid key path type\n";
+      abort();
+    }
 
     static bool hasEnclosingFunctionContext(DeclContext *dc) {
       switch (dc->getContextKind()) {
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index e29a206..50d58a3 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -340,6 +340,7 @@
   case DAK_AccessControl:
   case DAK_Ownership:
   case DAK_Effects:
+  case DAK_Optimize:
     if (DeclAttribute::isDeclModifier(getKind())) {
       Printer.printKeyword(getAttrName());
     } else {
@@ -577,6 +578,18 @@
     }
     llvm_unreachable("Invalid inline kind");
   }
+  case DAK_Optimize: {
+    switch (cast<OptimizeAttr>(this)->getMode()) {
+    case OptimizationMode::NoOptimization:
+      return "_optimize(none)";
+    case OptimizationMode::ForSpeed:
+      return "_optimize(speed)";
+    case OptimizationMode::ForSize:
+      return "_optimize(size)";
+    default:
+      llvm_unreachable("Invalid optimization kind");
+    }
+  }
   case DAK_Effects:
     switch (cast<EffectsAttr>(this)->getKind()) {
       case EffectsKind::ReadNone:
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index cc69513..2559621 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -80,6 +80,8 @@
     return Context.TheUnknownObjectType;
   if (Name == "BridgeObject")
     return Context.TheBridgeObjectType;
+  if (Name == "SILToken")
+    return Context.TheSILTokenType;
   if (Name == "UnsafeValueBuffer")
     return Context.TheUnsafeValueBufferType;
   
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index df45aec..6cd7c59 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -48,7 +48,6 @@
   SyntaxASTMap.cpp
   SILLayout.cpp
   Stmt.cpp
-  SourceEntityWalker.cpp
   Substitution.cpp
   SubstitutionList.cpp
   SubstitutionMap.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d276857..4233676 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -361,6 +361,15 @@
   llvm_unreachable("Unknown decl kind");
 }
 
+SourceRange Decl::getSourceRangeIncludingAttrs() const {
+  auto Range = getSourceRange();
+  for (auto Attr : getAttrs()) {
+    if (Attr->getRange().isValid())
+      Range.widen(Attr->getRange());
+  }
+  return Range;
+}
+
 SourceLoc Decl::getLoc() const {
   switch (getKind()) {
 #define DECL(ID, X) \
@@ -2175,6 +2184,19 @@
   llvm_unreachable("unknown access level");
 }
 
+void ValueDecl::copyFormalAccessAndVersionedAttrFrom(ValueDecl *source) {
+  if (!hasAccess()) {
+    setAccess(source->getFormalAccess());
+  }
+
+  // Inherit the @_versioned attribute.
+  if (source->getAttrs().hasAttribute<VersionedAttr>()) {
+    auto &ctx = getASTContext();
+    auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
+    getAttrs().add(clonedAttr);
+  }
+}
+
 Type TypeDecl::getDeclaredInterfaceType() const {
   if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
     return NTD->getDeclaredInterfaceType();
@@ -2680,9 +2702,9 @@
   return cast<DestructorDecl>(results.front());
 }
 
-DestructorDecl *ClassDecl::addImplicitDestructor() {
+void ClassDecl::addImplicitDestructor() {
   if (hasDestructor() || isInvalid())
-    return nullptr;
+    return;
 
   auto *selfDecl = ParamDecl::createSelf(getLoc(), this);
 
@@ -2690,12 +2712,36 @@
   auto *DD = new (ctx) DestructorDecl(getLoc(), selfDecl, this);
 
   DD->setImplicit();
+  DD->setValidationStarted();
 
   // Create an empty body for the destructor.
   DD->setBody(BraceStmt::create(ctx, getLoc(), { }, getLoc(), true));
   addMember(DD);
   setHasDestructor();
-  return DD;
+
+  // Propagate access control and versioned-ness.
+  DD->copyFormalAccessAndVersionedAttrFrom(this);
+
+  // Wire up generic environment of DD.
+  DD->setGenericEnvironment(getGenericEnvironmentOfContext());
+
+  // Mark DD as ObjC, as all dtors are.
+  DD->setIsObjC(true);
+  recordObjCMethod(DD);
+
+  // Assign DD the interface type (Self) -> () -> ()
+  ArrayRef<AnyFunctionType::Param> noParams;
+  AnyFunctionType::ExtInfo info;
+  Type selfTy = selfDecl->getInterfaceType();
+  Type voidTy = TupleType::getEmpty(ctx);
+  Type funcTy = FunctionType::get(noParams, voidTy, info);
+  if (auto *sig = DD->getGenericSignature()) {
+    DD->setInterfaceType(
+      GenericFunctionType::get(sig, {selfTy}, funcTy, info));
+  } else {
+    DD->setInterfaceType(
+      FunctionType::get({selfTy}, funcTy, info));
+  }
 }
 
 
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index e414b58..0c3221c 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -436,6 +436,23 @@
   return getParent();
 }
 
+DeclContext *DeclContext::getCommonParentContext(DeclContext *A,
+                                                 DeclContext *B) {
+  if (A == B)
+    return A;
+
+  if (A->isChildContextOf(B))
+    return B;
+
+  // Peel away layers of A until we reach a common parent
+  for (DeclContext *CurDC = A; CurDC; CurDC = CurDC->getParent()) {
+    if (B->isChildContextOf(CurDC))
+      return CurDC;
+  }
+
+  return nullptr;
+}
+
 ModuleDecl *DeclContext::getParentModule() const {
   const DeclContext *DC = this;
   while (!DC->isModuleContext())
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 2b31ca1..4279839 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -20,6 +20,7 @@
 #include "swift/AST/Decl.h"
 #include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/Module.h"
+#include "swift/AST/PrettyStackTrace.h"
 #include "swift/AST/Types.h"
 #include "swift/Basic/STLExtras.h"
 #include <functional>
@@ -174,6 +175,18 @@
   return getCanonicalSignature() == this;
 }
 
+#ifndef NDEBUG
+/// Determine the canonical ordering of requirements.
+static unsigned getRequirementKindOrder(RequirementKind kind) {
+  switch (kind) {
+  case RequirementKind::Conformance: return 2;
+  case RequirementKind::Superclass: return 0;
+  case RequirementKind::SameType: return 3;
+  case RequirementKind::Layout: return 1;
+  }
+}
+#endif
+
 CanGenericSignature GenericSignature::getCanonical(
                                         ArrayRef<GenericTypeParamType *> params,
                                         ArrayRef<Requirement> requirements) {
@@ -197,8 +210,105 @@
           Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(),
                       reqt.getLayoutConstraint()));
   }
+
   auto canSig = get(canonicalParams, canonicalRequirements,
                     /*isKnownCanonical=*/true);
+
+#ifndef NDEBUG
+  PrettyStackTraceGenericSignature debugStack("canonicalizing", canSig);
+
+  // Check that the signature is canonical.
+  for (unsigned idx : indices(canonicalRequirements)) {
+    debugStack.setRequirement(idx);
+
+    const auto &reqt = canonicalRequirements[idx];
+
+    // Left-hand side must be canonical in its context.
+    // Check canonicalization of requirement itself.
+    switch (reqt.getKind()) {
+    case RequirementKind::Superclass:
+      assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+             "Left-hand side is not canonical");
+      assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+             "Superclass type isn't canonical in its own context");
+      break;
+
+    case RequirementKind::Layout:
+      assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+             "Left-hand side is not canonical");
+      break;
+
+    case RequirementKind::SameType:
+      assert(reqt.getFirstType()->isTypeParameter() &&
+             "Left-hand side must be a type parameter");
+      if (reqt.getSecondType()->isTypeParameter()) {
+        assert(compareDependentTypes(reqt.getFirstType(), reqt.getSecondType())
+                 < 0 &&
+               "Out-of-order type parameters in same-type constraint");
+      } else {
+        assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+               "Concrete same-type isn't canonical in its own context");
+      }
+      break;
+
+    case RequirementKind::Conformance:
+      assert(reqt.getFirstType()->isTypeParameter() &&
+             "Left-hand side must be a type parameter");
+      assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
+             "Right-hand side of conformance isn't a protocol type");
+      break;
+    }
+
+    // From here on, we're only interested in requirements beyond the first.
+    if (idx == 0) continue;
+
+    // Make sure that the left-hand sides are in nondecreasing order.
+    const auto &prevReqt = canonicalRequirements[idx-1];
+    int compareLHS =
+      compareDependentTypes(prevReqt.getFirstType(), reqt.getFirstType());
+    assert(compareLHS <= 0 && "Out-of-order left-hand sides");
+
+    // If we have two same-type requirements where the left-hand sides differ
+    // but fall into the same equivalence class, we can check the form.
+    if (compareLHS < 0 && reqt.getKind() == RequirementKind::SameType &&
+        prevReqt.getKind() == RequirementKind::SameType &&
+        canSig->areSameTypeParameterInContext(prevReqt.getFirstType(),
+                                              reqt.getFirstType())) {
+      // If it's a it's a type parameter, make sure the equivalence class is
+      // wired together sanely.
+      if (prevReqt.getSecondType()->isTypeParameter()) {
+        assert(prevReqt.getSecondType()->isEqual(reqt.getFirstType()) &&
+               "same-type constraints within an equiv. class are out-of-order");
+      } else {
+        // Otherwise, the concrete types must match up.
+        assert(prevReqt.getSecondType()->isEqual(reqt.getSecondType()) &&
+               "inconsistent concrete same-type constraints in equiv. class");
+      }
+    }
+
+    // From here on, we only care about cases where the previous and current
+    // requirements have the same left-hand side.
+    if (compareLHS != 0) continue;
+
+    // Check ordering of requirement kinds.
+    assert((getRequirementKindOrder(prevReqt.getKind()) <=
+            getRequirementKindOrder(reqt.getKind())) &&
+           "Requirements for a given kind are out-of-order");
+
+    // From here on, we only care about the same requirement kind.
+    if (prevReqt.getKind() != reqt.getKind()) continue;
+
+    assert(reqt.getKind() == RequirementKind::Conformance &&
+           "Only conformance requirements can have multiples");
+
+    auto prevProto =
+      prevReqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+    auto proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+    assert(ProtocolType::compareProtocols(&prevProto, &proto) < 0 &&
+           "Out-of-order conformance requirements");
+  }
+#endif
+
   return CanGenericSignature(canSig);
 }
 
@@ -621,14 +731,12 @@
                              type1,
                              ArchetypeResolutionKind::CompleteWellFormed);
   assert(equivClass1 && "not a valid dependent type of this signature?");
-  assert(!equivClass1->concreteType);
 
   auto equivClass2 =
     builder.resolveEquivalenceClass(
                              type2,
                              ArchetypeResolutionKind::CompleteWellFormed);
   assert(equivClass2 && "not a valid dependent type of this signature?");
-  assert(!equivClass2->concreteType);
 
   return equivClass1 == equivClass2;
 }
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 4aada77..f0d7135 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -25,6 +25,7 @@
 #include "swift/AST/LazyResolver.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/ParameterList.h"
+#include "swift/AST/PrettyStackTrace.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/AST/TypeMatcher.h"
 #include "swift/AST/TypeRepr.h"
@@ -2954,36 +2955,30 @@
 
 /// Resolve any unresolved dependent member types using the given builder.
 static Type resolveDependentMemberTypes(GenericSignatureBuilder &builder,
-                                        Type type,
-                                        ArchetypeResolutionKind kind) {
+                                        Type type) {
   if (!type->hasTypeParameter()) return type;
 
-  return type.transformRec([&builder,kind](TypeBase *type) -> Optional<Type> {
-    if (auto depTy = dyn_cast<DependentMemberType>(type)) {
-      if (depTy->getAssocType()) return None;
+  return type.transformRec([&builder](TypeBase *type) -> Optional<Type> {
+    if (!type->isTypeParameter())
+      return None;
 
-      Type newBase =
-        resolveDependentMemberTypes(builder, depTy->getBase(), kind);
-      if (newBase->is<ErrorType>())
-        return ErrorType::get(depTy);
+    // Map the type parameter to an equivalence class.
+    auto equivClass =
+      builder.resolveEquivalenceClass(Type(type),
+                                      ArchetypeResolutionKind::WellFormed);
+    if (!equivClass)
+      return ErrorType::get(Type(type));
 
-      auto parentEquivClass = builder.resolveEquivalenceClass(newBase, kind);
-      if (!parentEquivClass)
-        return ErrorType::get(depTy);
+    // If there is a concrete type in this equivalence class, use that.
+    if (equivClass->concreteType) {
+      // .. unless it's recursive.
+      if (equivClass->recursiveConcreteType)
+        return ErrorType::get(Type(type));
 
-      auto memberType =
-        parentEquivClass->lookupNestedType(builder, depTy->getName());
-      if (!memberType)
-        return ErrorType::get(depTy);
-
-      if (auto assocType = dyn_cast<AssociatedTypeDecl>(memberType))
-        return Type(DependentMemberType::get(newBase, assocType));
-
-      // FIXME: Need to substitute here.
-      return Type(type);
+      return resolveDependentMemberTypes(builder, equivClass->concreteType);
     }
 
-    return None;
+    return equivClass->getAnchor(builder, builder.getGenericParams());
   });
 }
 
@@ -3094,9 +3089,7 @@
   // FIXME: Generic typealiases contradict the assumption above.
   // If there is a type parameter somewhere in this type, resolve it.
   if (type->hasTypeParameter()) {
-    Type resolved =
-    resolveDependentMemberTypes(*this, type,
-                                ArchetypeResolutionKind::WellFormed);
+    Type resolved = resolveDependentMemberTypes(*this, type);
     if (resolved->hasError() && !type->hasError())
       return ResolvedType::forUnresolved(nullptr);
 
@@ -5951,10 +5944,9 @@
     diag::redundant_same_type_to_concrete,
     diag::same_type_redundancy_here);
 
-  // Resolve any this-far-unresolved dependent types.
+  // Resolve any thus-far-unresolved dependent types.
   equivClass->concreteType =
-    resolveDependentMemberTypes(*this, equivClass->concreteType,
-                                ArchetypeResolutionKind::CompleteWellFormed);
+    resolveDependentMemberTypes(*this, equivClass->concreteType);
 }
 
 void GenericSignatureBuilder::checkSuperclassConstraints(
@@ -5996,8 +5988,7 @@
 
   // Resolve any this-far-unresolved dependent types.
   equivClass->superclass =
-    resolveDependentMemberTypes(*this, equivClass->superclass,
-                                ArchetypeResolutionKind::CompleteWellFormed);
+    resolveDependentMemberTypes(*this, equivClass->superclass);
 
   // If we have a concrete type, check it.
   // FIXME: Substitute into the concrete type.
@@ -6374,7 +6365,7 @@
   // over-minimizing.
   if (allowBuilderToMove && !Impl->HadAnyError &&
       !Impl->HadAnyRedundantConstraints) {
-    // Register this generic signature builer as the canonical builder for the
+    // Register this generic signature builder as the canonical builder for the
     // given signature.
     Context.registerGenericSignatureBuilder(sig, std::move(*this));
   }
@@ -6412,3 +6403,77 @@
            /*allowBuilderToMove=*/false);
 }
 
+#pragma mark Generic signature verification
+
+void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
+                                                     GenericSignature *sig) {
+  llvm::errs() << "Validating generic signature: ";
+  sig->print(llvm::errs());
+  llvm::errs() << "\n";
+
+  // Try removing each requirement in turn.
+  auto genericParams = sig->getGenericParams();
+  auto requirements = sig->getRequirements();
+  for (unsigned victimIndex : indices(requirements)) {
+    PrettyStackTraceGenericSignature debugStack("verifying", sig, victimIndex);
+
+    // Form a new generic signature builder.
+    GenericSignatureBuilder builder(context);
+
+    // Add the generic parameters.
+    for (auto gp : genericParams)
+      builder.addGenericParameter(gp);
+
+    // Add the requirements *except* the victim.
+    auto source = FloatingRequirementSource::forAbstract();
+    for (unsigned i : indices(requirements)) {
+      if (i != victimIndex)
+        builder.addRequirement(requirements[i], source, nullptr);
+    }
+
+    // Finalize the generic signature. If there were any errors, we formed
+    // an invalid signature, so just continue.
+    if (builder.Impl->HadAnyError) continue;
+
+    // Form a generic signature from the result.
+    auto newSig =
+      std::move(builder).computeGenericSignature(
+                                      SourceLoc(),
+                                      /*allowConcreteGenericParams=*/true,
+                                      /*allowBuilderToMove=*/true);
+
+    // Check whether the removed requirement
+    assert(!newSig->isRequirementSatisfied(requirements[victimIndex]) &&
+           "Generic signature is not minimal");
+
+    // Canonicalize the signature to check that it is canonical.
+    (void)newSig->getCanonicalSignature();
+  }
+}
+
+void GenericSignatureBuilder::verifyGenericSignaturesInModule(
+                                                        ModuleDecl *module) {
+  LoadedFile *loadedFile = nullptr;
+  for (auto fileUnit : module->getFiles()) {
+    loadedFile = dyn_cast<LoadedFile>(fileUnit);
+    if (loadedFile) break;
+  }
+
+  if (!loadedFile) return;
+
+  // Check all of the (canonical) generic signatures.
+  SmallVector<GenericSignature *, 8> allGenericSignatures;
+  SmallPtrSet<CanGenericSignature, 4> knownGenericSignatures;
+  (void)loadedFile->getAllGenericSignatures(allGenericSignatures);
+  ASTContext &context = module->getASTContext();
+  for (auto genericSig : allGenericSignatures) {
+    // Check whether this is the first time we've checked this (canonical)
+    // signature.
+    auto canGenericSig = genericSig->getCanonicalSignature();
+    if (!knownGenericSignatures.insert(canGenericSig).second) continue;
+
+    verifyGenericSignature(context, canGenericSig);
+  }
+}
+
+
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index e64c8dd..f374f09 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -1176,7 +1176,8 @@
       return;
 
     auto nominal = getExtendedType()->getAnyNominal();
-    if (nominal->LookupTable.getPointer()) {
+    if (nominal->LookupTable.getPointer() &&
+        nominal->LookupTable.getInt()) {
       // Make sure we have the complete list of extensions.
       // FIXME: This is completely unnecessary. We want to determine whether
       // our own extension has already been included in the lookup table.
diff --git a/lib/AST/PrettyStackTrace.cpp b/lib/AST/PrettyStackTrace.cpp
index 26a1fb5..649baea 100644
--- a/lib/AST/PrettyStackTrace.cpp
+++ b/lib/AST/PrettyStackTrace.cpp
@@ -18,6 +18,7 @@
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/Expr.h"
+#include "swift/AST/GenericSignature.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/Pattern.h"
 #include "swift/AST/Stmt.h"
@@ -214,3 +215,12 @@
   out << "While " << Action << " starting at ";
   printSourceLocDescription(out, Loc, Context);
 }
+
+void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
+  out << "While " << Action << " generic signature ";
+  GenericSig->print(out);
+  if (Requirement) {
+    out << " in requirement #" << *Requirement;
+  }
+  out << '\n';
+}
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 5984052..1e38106 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -116,8 +116,6 @@
   if (auto result = conformances(origType->getCanonicalType(),
                                  substType,
                                  proto->getDeclaredType())) {
-    assert(result->getConditionalRequirements().empty() &&
-           "unhandled conditional requirements");
     return *result;
   }
 
@@ -288,6 +286,45 @@
   llvm_unreachable("Unhandled ProtocolConformanceKind in switch.");
 }
 
+SubstitutionMap ProtocolConformance::getSubstitutions(ModuleDecl *M) const {
+  // Walk down to the base NormalProtocolConformance.
+  SubstitutionMap subMap;
+  const ProtocolConformance *parent = this;
+  while (!isa<NormalProtocolConformance>(parent)) {
+    switch (parent->getKind()) {
+    case ProtocolConformanceKind::Normal:
+      llvm_unreachable("should have exited the loop?!");
+    case ProtocolConformanceKind::Inherited:
+      parent =
+          cast<InheritedProtocolConformance>(parent)->getInheritedConformance();
+      break;
+    case ProtocolConformanceKind::Specialized: {
+      auto SC = cast<SpecializedProtocolConformance>(parent);
+      parent = SC->getGenericConformance();
+      assert(subMap.empty() && "multiple conformance specializations?!");
+      subMap = SC->getSubstitutionMap();
+      break;
+    }
+    }
+  }
+
+  // Found something; we're done!
+  if (!subMap.empty())
+    return subMap;
+
+  // If the normal conformance is for a generic type, and we didn't hit a
+  // specialized conformance, collect the substitutions from the generic type.
+  // FIXME: The AST should do this for us.
+  const NormalProtocolConformance *normalC =
+      cast<NormalProtocolConformance>(parent);
+
+  if (!normalC->getType()->isSpecialized())
+    return SubstitutionMap();
+
+  auto *DC = normalC->getDeclContext();
+  return normalC->getType()->getContextSubstitutionMap(M, DC);
+}
+
 bool ProtocolConformance::isBehaviorConformance() const {
   return getRootNormalConformance()->isBehaviorConformance();
 }
@@ -758,10 +795,9 @@
   auto *typeDecl = genericWitnessAndDecl.second;
 
   // Form the substitution.
-  auto *genericSig = GenericConformance->getGenericSignature();
-  if (!genericSig) return { Type(), nullptr };
-
-  auto substitutionMap = genericSig->getSubstitutionMap(GenericSubstitutions);
+  auto substitutionMap = getSubstitutionMap();
+  if (substitutionMap.empty())
+    return {Type(), nullptr};
 
   // Apply the substitution we computed above
   auto specializedType = genericWitness.subst(getSubstitutionMap(), options);
@@ -876,6 +912,10 @@
   return cast<NormalProtocolConformance>(C);
 }
 
+bool ProtocolConformance::witnessTableAccessorRequiresArguments() const {
+  return getRootNormalConformance()->getDeclContext()->isGenericContext();
+}
+
 bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
   // FIXME: Implement me!
   return true;
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d1291d5..d27e118 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -18,6 +18,7 @@
 #include "ForeignRepresentationInfo.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/GenericSignatureBuilder.h"
 #include "swift/AST/TypeVisitor.h"
 #include "swift/AST/TypeWalker.h"
 #include "swift/AST/Decl.h"
@@ -219,6 +220,7 @@
   case TypeKind::TypeVariable:
   case TypeKind::BoundGenericEnum:
   case TypeKind::BoundGenericStruct:
+  case TypeKind::SILToken:
   case TypeKind::UnownedStorage:
   case TypeKind::UnmanagedStorage:
   case TypeKind::WeakStorage:
@@ -1156,6 +1158,7 @@
   case TypeKind::SILBlockStorage:
   case TypeKind::SILBox:
   case TypeKind::SILFunction:
+  case TypeKind::SILToken:
     llvm_unreachable("SIL-only types are always canonical!");
 
   case TypeKind::Function: {
@@ -1275,6 +1278,7 @@
   case TypeKind::SILBlockStorage:
   case TypeKind::SILBox:
   case TypeKind::SILFunction:
+  case TypeKind::SILToken:
   case TypeKind::LValue:
   case TypeKind::InOut:
   case TypeKind::ProtocolComposition:
@@ -1493,6 +1497,7 @@
   case TypeKind::SILFunction:
   case TypeKind::SILBlockStorage:
   case TypeKind::SILBox:
+  case TypeKind::SILToken:
   case TypeKind::GenericFunction: {
     // Polymorphic function types should never be explicitly spelled.
     return false;
@@ -3089,15 +3094,110 @@
                               getAssocType(), getName(), None);
 }
 
+static Type substGenericFunctionType(GenericFunctionType *genericFnType,
+                                     TypeSubstitutionFn substitutions,
+                                     LookupConformanceFn lookupConformances,
+                                     SubstOptions options) {
+  // Substitute into the function type (without generic signature).
+  auto *bareFnType = FunctionType::get(genericFnType->getInput(),
+                                       genericFnType->getResult(),
+                                       genericFnType->getExtInfo());
+  Type result =
+    Type(bareFnType).subst(substitutions, lookupConformances, options);
+  if (!result || result->is<ErrorType>()) return result;
+
+  auto *fnType = result->castTo<FunctionType>();
+  // Substitute generic parameters.
+  bool anySemanticChanges = false;
+  SmallVector<GenericTypeParamType *, 4> genericParams;
+  for (auto param : genericFnType->getGenericParams()) {
+    Type paramTy =
+      Type(param).subst(substitutions, lookupConformances, options);
+    if (!paramTy)
+      return Type();
+
+    if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
+      if (!newParam->isEqual(param))
+        anySemanticChanges = true;
+
+      genericParams.push_back(newParam);
+    } else {
+      anySemanticChanges = true;
+    }
+  }
+
+  // If no generic parameters remain, this is a non-generic function type.
+  if (genericParams.empty())
+    return result;
+
+  // Transform requirements.
+  SmallVector<Requirement, 4> requirements;
+  for (const auto &req : genericFnType->getRequirements()) {
+    // Substitute into the requirement.
+    auto substReqt = req.subst(substitutions, lookupConformances, options);
+    if (!substReqt) {
+      anySemanticChanges = true;
+      continue;
+    }
+
+    // Did anything change?
+    if (!anySemanticChanges &&
+        (!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
+         (req.getKind() != RequirementKind::Layout &&
+          !req.getSecondType()->isEqual(substReqt->getSecondType())))) {
+      anySemanticChanges = true;
+    }
+
+    // Skip any erroneous requirements.
+    if (substReqt->getFirstType()->hasError() ||
+        (substReqt->getKind() != RequirementKind::Layout &&
+         substReqt->getSecondType()->hasError()))
+      continue;
+
+    requirements.push_back(*substReqt);
+  }
+
+  GenericSignature *genericSig = nullptr;
+  if (anySemanticChanges) {
+    // If there were semantic changes, we need to build a new generic
+    // signature.
+    GenericSignatureBuilder builder(genericFnType->getASTContext());
+
+    // Add the generic parameters to the builder.
+    for (auto gp : genericParams)
+      builder.addGenericParameter(gp);
+
+    // Add the requirements to the builder.
+    auto source =
+      GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+    for (const auto &req : requirements)
+      builder.addRequirement(req, source, /*inferForModule=*/nullptr);
+
+    // Form the generic signature.
+    genericSig = std::move(builder).computeGenericSignature(SourceLoc());
+  } else {
+    // Use the mapped generic signature.
+    genericSig = GenericSignature::get(genericParams, requirements);
+  }
+
+  // Produce the new generic function type.
+  return GenericFunctionType::get(genericSig, fnType->getInput(),
+                                  fnType->getResult(), fnType->getExtInfo());
+}
+
 static Type substType(Type derivedType,
                       TypeSubstitutionFn substitutions,
                       LookupConformanceFn lookupConformances,
                       SubstOptions options) {
+  // Handle substitutions into generic function types.
+  if (auto genericFnType = derivedType->getAs<GenericFunctionType>()) {
+    return substGenericFunctionType(genericFnType, substitutions,
+                                    lookupConformances, options);
+  }
 
   // FIXME: Change getTypeOfMember() to not pass GenericFunctionType here
   if (!derivedType->hasArchetype() &&
-      !derivedType->hasTypeParameter() &&
-      !derivedType->is<GenericFunctionType>())
+      !derivedType->hasTypeParameter())
     return derivedType;
 
   return derivedType.transformRec([&](TypeBase *type) -> Optional<Type> {
@@ -3236,17 +3336,22 @@
 
 Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
   Type t(this);
+
+  if (!t->getAnyNominal()) {
+    if (auto archetype = t->getAs<ArchetypeType>()) {
+      t = archetype->getSuperclass();
+    } else if (auto dynamicSelfTy = t->getAs<DynamicSelfType>()) {
+      t = dynamicSelfTy->getSelfType();
+    } else if (auto compositionTy = t->getAs<ProtocolCompositionType>()) {
+      t = compositionTy->getExistentialLayout().superclass;
+    }
+  }
+
   while (t) {
     // If we have a class-constrained archetype or class-constrained
     // existential, get the underlying superclass constraint.
     auto *nominalDecl = t->getAnyNominal();
-    if (!nominalDecl) {
-      assert(t->is<ArchetypeType>() || t->isExistentialType() &&
-             "expected a class, archetype or existential");
-      t = t->getSuperclass();
-      assert(t && "archetype or existential is not class constrained");
-      continue;
-    }
+    assert(nominalDecl && "expected nominal type here");
     assert(isa<ClassDecl>(nominalDecl) && "expected a class here");
 
     if (nominalDecl == baseClass)
@@ -3263,7 +3368,9 @@
   assert(dc->isTypeContext());
   Type baseTy(this);
 
-  assert(!baseTy->hasLValueType() && !baseTy->is<AnyMetatypeType>());
+  assert(!baseTy->hasLValueType() &&
+         !baseTy->is<AnyMetatypeType>() &&
+         !baseTy->is<ErrorType>());
 
   // The resulting set of substitutions. Always use this to ensure we
   // don't miss out on NRVO anywhere.
@@ -3409,6 +3516,7 @@
 
   assert(memberType);
 
+  // Perform the substitution.
   auto substitutions = getMemberSubstitutionMap(module, member);
   return memberType.subst(substitutions, SubstFlags::UseErrorType);
 }
@@ -3463,6 +3571,20 @@
   return false;
 }
 
+static bool transformSILYield(
+                            SILYieldInfo &yield, bool &changed,
+                            llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
+  Type transType = yield.getType().transformRec(fn);
+  if (!transType) return true;
+
+  CanType canTransType = transType->getCanonicalType();
+  if (canTransType != yield.getType()) {
+    changed = true;
+    yield = yield.getWithType(canTransType);
+  }
+  return false;
+}
+
 static bool transformSILParameter(
                             SILParameterInfo &param, bool &changed,
                             llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
@@ -3513,6 +3635,7 @@
   case TypeKind::Unresolved:
   case TypeKind::TypeVariable:
   case TypeKind::GenericTypeParam:
+  case TypeKind::SILToken:
     return *this;
 
   case TypeKind::Enum:
@@ -3568,6 +3691,12 @@
       transInterfaceParams.push_back(param);
     }
 
+    SmallVector<SILYieldInfo, 8> transInterfaceYields;
+    for (SILYieldInfo yield : fnTy->getYields()) {
+      if (transformSILYield(yield, changed, fn)) return Type();
+      transInterfaceYields.push_back(yield);
+    }
+
     SmallVector<SILResultInfo, 8> transInterfaceResults;
     for (SILResultInfo result : fnTy->getResults()) {
       if (transformSILResult(result, changed, fn)) return Type();
@@ -3583,10 +3712,15 @@
 
     if (!changed) return *this;
 
-    return SILFunctionType::get(fnTy->getGenericSignature(), fnTy->getExtInfo(),
+    return SILFunctionType::get(fnTy->getGenericSignature(),
+                                fnTy->getExtInfo(),
+                                fnTy->getCoroutineKind(),
                                 fnTy->getCalleeConvention(),
-                                transInterfaceParams, transInterfaceResults,
-                                transErrorResult, Ptr->getASTContext(),
+                                transInterfaceParams,
+                                transInterfaceYields,
+                                transInterfaceResults,
+                                transErrorResult,
+                                Ptr->getASTContext(),
                                 fnTy->getWitnessMethodConformanceOrNone());
   }
 
@@ -3777,6 +3911,7 @@
     return DependentMemberType::get(dependentBase, dependent->getName());
   }
 
+  case TypeKind::GenericFunction:
   case TypeKind::Function: {
     auto function = cast<AnyFunctionType>(base);
     auto inputTy = function->getInput().transformRec(fn);
@@ -3786,131 +3921,33 @@
     if (!resultTy)
       return Type();
 
-    if (inputTy.getPointer() == function->getInput().getPointer() &&
-        resultTy.getPointer() == function->getResult().getPointer())
-      return *this;
+    bool isUnchanged =
+        inputTy.getPointer() == function->getInput().getPointer() &&
+        resultTy.getPointer() == function->getResult().getPointer();
+
+    if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
+
+#ifndef NDEBUG
+      // Check that generic parameters won't be trasnformed.
+      // Transform generic parameters.
+      for (auto param : genericFnType->getGenericParams()) {
+        assert(Type(param).transformRec(fn).getPointer() == param &&
+               "GenericFunctionType transform() changes type parameter");
+      }
+#endif
+      if (isUnchanged) return *this;
+      
+      auto genericSig = genericFnType->getGenericSignature();
+      return GenericFunctionType::get(genericSig, inputTy, resultTy,
+                                      function->getExtInfo());
+    }
+
+    if (isUnchanged) return *this;
 
     return FunctionType::get(inputTy, resultTy,
                              function->getExtInfo());
   }
 
-  case TypeKind::GenericFunction: {
-    GenericFunctionType *function = cast<GenericFunctionType>(base);
-    bool anyChanges = false;
-
-    // Transform generic parameters.
-    SmallVector<GenericTypeParamType *, 4> genericParams;
-    for (auto param : function->getGenericParams()) {
-      Type paramTy = Type(param).transformRec(fn);
-      if (!paramTy)
-        return Type();
-
-      if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
-        if (newParam != param)
-          anyChanges = true;
-
-        genericParams.push_back(newParam);
-      } else {
-        anyChanges = true;
-      }
-    }
-
-    // Transform requirements.
-    SmallVector<Requirement, 4> requirements;
-    for (const auto &req : function->getRequirements()) {
-      auto firstType = req.getFirstType().transformRec(fn);
-      if (!firstType)
-        return Type();
-
-      if (firstType.getPointer() != req.getFirstType().getPointer())
-        anyChanges = true;
-
-      if (req.getKind() == RequirementKind::Layout) {
-        if (!firstType->isTypeParameter())
-          continue;
-
-        requirements.push_back(Requirement(req.getKind(), firstType,
-                                           req.getLayoutConstraint()));
-        continue;
-      }
-
-      Type secondType = req.getSecondType();
-      if (secondType) {
-        secondType = secondType.transformRec(fn);
-        if (!secondType)
-          return Type();
-
-        if (secondType.getPointer() != req.getSecondType().getPointer())
-          anyChanges = true;
-      }
-
-      if (!firstType->isTypeParameter()) {
-        if (!secondType || !secondType->isTypeParameter())
-          continue;
-        std::swap(firstType, secondType);
-      }
-
-      requirements.push_back(Requirement(req.getKind(), firstType,
-                                         secondType));
-    }
-    
-    // Transform input type.
-    auto inputTy = function->getInput().transformRec(fn);
-    if (!inputTy)
-      return Type();
-
-    // Transform result type.
-    auto resultTy = function->getResult().transformRec(fn);
-    if (!resultTy)
-      return Type();
-
-    // Check whether anything changed.
-    if (!anyChanges &&
-        inputTy.getPointer() == function->getInput().getPointer() &&
-        resultTy.getPointer() == function->getResult().getPointer())
-      return *this;
-
-    // If no generic parameters remain, this is a non-generic function type.
-    if (genericParams.empty()) {
-      return FunctionType::get(inputTy, resultTy, function->getExtInfo());
-    }
-
-    // Sort/unique the generic parameters by depth/index.
-    using llvm::array_pod_sort;
-    array_pod_sort(genericParams.begin(), genericParams.end(),
-                   [](GenericTypeParamType * const * gpp1,
-                      GenericTypeParamType * const * gpp2) {
-                     auto gp1 = *gpp1;
-                     auto gp2 = *gpp2;
-
-                     if (gp1->getDepth() < gp2->getDepth())
-                       return -1;
-
-                     if (gp1->getDepth() > gp2->getDepth())
-                       return 1;
-
-                     if (gp1->getIndex() < gp2->getIndex())
-                       return -1;
-
-                     if (gp1->getIndex() > gp2->getIndex())
-                       return 1;
-
-                     return 0;
-                   });
-    genericParams.erase(std::unique(genericParams.begin(), genericParams.end(),
-                                    [](GenericTypeParamType *gp1,
-                                       GenericTypeParamType *gp2) {
-                                      return gp1->getDepth() == gp2->getDepth()
-                                          && gp1->getIndex() == gp2->getIndex();
-                                    }),
-                        genericParams.end());
-
-    // Produce the new generic function type.
-    auto sig = GenericSignature::get(genericParams, requirements);
-    return GenericFunctionType::get(sig, inputTy, resultTy,
-                                    function->getExtInfo());
-  }
-
   case TypeKind::ArraySlice: {
     auto slice = cast<ArraySliceType>(base);
     auto baseTy = slice->getBaseType().transformRec(fn);
@@ -4184,6 +4221,7 @@
   case TypeKind::TypeVariable:
   case TypeKind::BoundGenericEnum:
   case TypeKind::BoundGenericStruct:
+  case TypeKind::SILToken:
   case TypeKind::UnownedStorage:
   case TypeKind::UnmanagedStorage:
   case TypeKind::WeakStorage:
diff --git a/lib/AST/TypeWalker.cpp b/lib/AST/TypeWalker.cpp
index 70e1061..56877a6 100644
--- a/lib/AST/TypeWalker.cpp
+++ b/lib/AST/TypeWalker.cpp
@@ -36,6 +36,7 @@
   bool visitUnresolvedType(UnresolvedType *ty) { return false; }
   bool visitBuiltinType(BuiltinType *ty) { return false; }
   bool visitNameAliasType(NameAliasType *ty) { return false; }
+  bool visitSILTokenType(SILTokenType *ty) { return false; }
 
   bool visitParenType(ParenType *ty) {
     return doIt(ty->getUnderlyingType());
diff --git a/lib/Basic/SourceLoc.cpp b/lib/Basic/SourceLoc.cpp
index a96c4e9..f55af89 100644
--- a/lib/Basic/SourceLoc.cpp
+++ b/lib/Basic/SourceLoc.cpp
@@ -205,6 +205,13 @@
   llvm_unreachable("no buffer containing location found");
 }
 
+void SourceRange::widen(SourceRange Other) {
+  if (Other.Start.Value.getPointer() < Start.Value.getPointer())
+    Start = Other.Start;
+  if (Other.End.Value.getPointer() > End.Value.getPointer())
+    End = Other.End;
+}
+
 void SourceLoc::printLineAndColumn(raw_ostream &OS,
                                    const SourceManager &SM) const {
   if (isInvalid()) {
diff --git a/lib/Basic/Statistic.cpp b/lib/Basic/Statistic.cpp
index 765e9ed..46ee77f 100644
--- a/lib/Basic/Statistic.cpp
+++ b/lib/Basic/Statistic.cpp
@@ -143,7 +143,9 @@
                                            StringRef Directory,
                                            SourceManager *SM,
                                            bool TraceEvents)
-  : StatsFilename(Directory),
+  : currentProcessExitStatusSet(false),
+    currentProcessExitStatus(EXIT_FAILURE),
+    StatsFilename(Directory),
     TraceFilename(Directory),
     StartedTime(llvm::TimeRecord::getCurrentTime()),
     Timer(make_unique<NamedRegionTimer>(AuxName,
@@ -184,6 +186,13 @@
 }
 
 void
+UnifiedStatsReporter::noteCurrentProcessExitStatus(int status) {
+  assert(!currentProcessExitStatusSet);
+  currentProcessExitStatusSet = true;
+  currentProcessExitStatus = status;
+}
+
+void
 UnifiedStatsReporter::publishAlwaysOnStatsToLLVM() {
   if (FrontendCounters) {
     auto &C = getFrontendCounters();
@@ -334,6 +343,18 @@
 
 UnifiedStatsReporter::~UnifiedStatsReporter()
 {
+  // If nobody's marked this process as successful yet,
+  // mark it as failing.
+  if (currentProcessExitStatus != EXIT_SUCCESS) {
+    if (FrontendCounters) {
+      auto &C = getFrontendCounters();
+      C.NumProcessFailures++;
+    } else {
+      auto &C = getDriverCounters();
+      C.NumProcessFailures++;
+    }
+  }
+
   // NB: Timer needs to be Optional<> because it needs to be destructed early;
   // LLVM will complain about double-stopping a timer if you tear down a
   // NamedRegionTimer after printing all timers. The printing routines were
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 40c58a4..3982bd6 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4254,7 +4254,7 @@
         result->setCheckedInheritanceClause();
         result->setAddedImplicitInitializers(); // suppress all initializers
         addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
-        Impl.registerExternalDecl(result);
+        result->addImplicitDestructor();
         return result;
       };
 
@@ -4274,7 +4274,6 @@
         auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
                                       nsObjectDecl->getDeclContext());
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
         return result;
       }
 
@@ -4359,7 +4358,6 @@
         markMissingSwiftDecl(result);
       if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>()) {
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
       }
 
       // If this Objective-C class has a supertype, import it.
@@ -4392,7 +4390,6 @@
       if (decl->getName() == "OS_object" ||
           decl->getName() == "OS_os_log") {
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
-        result->addImplicitDestructor();
       }
 
       // If the superclass is runtime-only, our class is also. This only
@@ -4420,9 +4417,7 @@
 #include "InferredAttributes.def"
 
       result->setMemberLoader(&Impl, 0);
-
-      // Pass the class to the type checker to create an implicit destructor.
-      Impl.registerExternalDecl(result);
+      result->addImplicitDestructor();
 
       return result;
     }
diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp
index 161f1e9..845f2b7 100644
--- a/lib/ClangImporter/ImportName.cpp
+++ b/lib/ClangImporter/ImportName.cpp
@@ -839,7 +839,7 @@
   if (!contextType.isNull()) {
     if (auto objcPtrType = contextType->getAsObjCInterfacePointerType())
       if (auto objcClassDecl = objcPtrType->getInterfaceDecl())
-        allPropertyNames = nameImporter.getContext().getAllPropertyNames(
+        allPropertyNames = nameImporter.getAllPropertyNames(
             objcClassDecl, isInstanceMethod);
   }
 
@@ -1655,8 +1655,7 @@
           if (auto objcPtrType = contextType->getAsObjCInterfacePointerType())
             if (auto objcClassDecl = objcPtrType->getInterfaceDecl())
               allPropertyNames =
-                  swiftCtx.getAllPropertyNames(objcClassDecl,
-                                               /*forInstance=*/true);
+                  getAllPropertyNames(objcClassDecl, /*forInstance=*/true);
         }
 
         (void)omitNeedlessWords(baseName, {}, "", propertyTypeName,
@@ -1774,3 +1773,72 @@
     importNameCache[key] = res;
   return res;
 }
+
+const InheritedNameSet *NameImporter::getAllPropertyNames(
+                          clang::ObjCInterfaceDecl *classDecl,
+                          bool forInstance) {
+  classDecl = classDecl->getCanonicalDecl();
+
+  // If we already have this information, return it.
+  auto known = allProperties.find({classDecl, forInstance});
+  if (known != allProperties.end()) return known->second.get();
+
+  // Otherwise, get information from our superclass first.
+  const InheritedNameSet *parentSet = nullptr;
+  if (auto superclassDecl = classDecl->getSuperClass()) {
+    parentSet = getAllPropertyNames(superclassDecl, forInstance);
+  }
+
+  // Create the set of properties.
+  known = allProperties.insert(
+            { std::pair<const clang::ObjCInterfaceDecl *, char>(classDecl,
+                                                                forInstance),
+              llvm::make_unique<InheritedNameSet>(parentSet) }).first;
+
+  // Local function to add properties from the given set.
+  auto addProperties = [&](clang::DeclContext::decl_range members) {
+    for (auto member : members) {
+      // Add Objective-C property names.
+      if (auto property = dyn_cast<clang::ObjCPropertyDecl>(member)) {
+        if (forInstance)
+          known->second->add(property->getName());
+        continue;
+      }
+
+      // Add no-parameter, non-void method names.
+      if (auto method = dyn_cast<clang::ObjCMethodDecl>(member)) {
+        if (method->getSelector().isUnarySelector() &&
+            !method->getReturnType()->isVoidType() &&
+            !method->hasRelatedResultType() &&
+            method->isInstanceMethod() == forInstance) {
+          known->second->add(method->getSelector().getNameForSlot(0));
+          continue;
+        }
+      }
+    }
+  };
+
+  // Dig out the class definition.
+  auto classDef = classDecl->getDefinition();
+  if (!classDef) return known->second.get();
+
+  // Collect property names from the class definition.
+  addProperties(classDef->decls());
+
+  // Dig out the module that owns the class definition.
+  auto module = classDef->getImportedOwningModule();
+  if (module) module = module->getTopLevelModule();
+
+  // Collect property names from all categories and extensions in the same
+  // module as the class.
+  for (auto category : classDef->known_categories()) {
+    auto categoryModule = category->getImportedOwningModule();
+    if (categoryModule) categoryModule = categoryModule->getTopLevelModule();
+    if (module != categoryModule) continue;
+
+    addProperties(category->decls());
+  }
+
+  return known->second.get();
+}
+
diff --git a/lib/ClangImporter/ImportName.h b/lib/ClangImporter/ImportName.h
index f993b02..b180f97 100644
--- a/lib/ClangImporter/ImportName.h
+++ b/lib/ClangImporter/ImportName.h
@@ -288,6 +288,11 @@
   /// Cache for repeated calls
   llvm::DenseMap<CacheKeyType, ImportedName> importNameCache;
 
+  /// The set of property names that show up in the defining module of
+  /// an Objective-C class.
+  llvm::DenseMap<std::pair<const clang::ObjCInterfaceDecl *, char>,
+                 std::unique_ptr<InheritedNameSet>> allProperties;
+
 public:
   NameImporter(ASTContext &ctx, const PlatformAvailability &avail,
                clang::Sema &cSema, bool inferIAM)
@@ -331,6 +336,11 @@
     return getClangSema().getPreprocessor();
   }
 
+  /// Retrieve the inherited name set for the given Objective-C class.
+  const InheritedNameSet *getAllPropertyNames(
+                            clang::ObjCInterfaceDecl *classDecl,
+                            bool forInstance);
+
 private:
   bool enableObjCInterop() const { return swiftCtx.LangOpts.EnableObjCInterop; }
 
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index a68dbf9..b40fe64 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -778,6 +778,9 @@
       Ty = createNode(Node::Kind::BuiltinTypeName,
                                "Builtin.RawPointer");
       break;
+    case 't':
+      Ty = createNode(Node::Kind::BuiltinTypeName, "Builtin.SILToken");
+      break;
     case 'w':
       Ty = createNode(Node::Kind::BuiltinTypeName,
                                "Builtin.Word");
@@ -1247,6 +1250,7 @@
 NodePointer Demangler::demangleThunkOrSpecialization() {
   switch (char c = nextChar()) {
     case 'c': return createWithChild(Node::Kind::CurryThunk, popNode(isEntity));
+    case 'j': return createWithChild(Node::Kind::DispatchThunk, popNode(isEntity));
     case 'o': return createNode(Node::Kind::ObjCAttribute);
     case 'O': return createNode(Node::Kind::NonObjCAttribute);
     case 'D': return createNode(Node::Kind::DynamicAttribute);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index aff802b..957b2f0 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -294,6 +294,7 @@
     case Node::Kind::CFunctionPointer:
     case Node::Kind::Constructor:
     case Node::Kind::CurryThunk:
+    case Node::Kind::DispatchThunk:
     case Node::Kind::Deallocator:
     case Node::Kind::DeclContext:
     case Node::Kind::DefaultArgumentInitializer:
@@ -798,6 +799,10 @@
     Printer << "curry thunk of ";
     print(Node->getChild(0));
     return nullptr;
+  case Node::Kind::DispatchThunk:
+    Printer << "dispatch thunk of ";
+    print(Node->getChild(0));
+    return nullptr;
   case Node::Kind::OutlinedBridgedMethod:
     Printer << "outlined bridged method (" << Node->getText() << ") of ";
     return nullptr;
diff --git a/lib/Demangling/OldDemangler.cpp b/lib/Demangling/OldDemangler.cpp
index 20ce3f0..b661596 100644
--- a/lib/Demangling/OldDemangler.cpp
+++ b/lib/Demangling/OldDemangler.cpp
@@ -1848,6 +1848,9 @@
       if (c == 'p')
         return Factory.createNode(Node::Kind::BuiltinTypeName,
                                      "Builtin.RawPointer");
+      if (c == 't')
+        return Factory.createNode(Node::Kind::BuiltinTypeName,
+                                     "Builtin.SILToken");
       if (c == 'w')
         return Factory.createNode(Node::Kind::BuiltinTypeName,
                                      "Builtin.Word");
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 3666b43..73bd301 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -1668,6 +1668,10 @@
   Out << "<curry-thunk>";
 }
 
+void Remangler::mangleDispatchThunk(Node *node, EntityContext &ctx) {
+  Out << "<dispatch-thunk>";
+}
+
 void Remangler::mangleEmptyList(Node *node) {
   Out << "<empty>";
 }
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 060cc24..146cdb5 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -579,6 +579,8 @@
     Buffer << 'o';
   } else if (text == "Builtin.RawPointer") {
     Buffer << 'p';
+  } else if (text == "Builtin.SILToken") {
+    Buffer << 't';
   } else if (text == "Builtin.Word") {
     Buffer << 'w';
   } else if (stripPrefix(text, "Builtin.Int")) {
@@ -1711,6 +1713,11 @@
   Buffer << "Tc";
 }
 
+void Remangler::mangleDispatchThunk(Node *node) {
+  mangleSingleChildNode(node);
+  Buffer << "Tj";
+}
+
 void Remangler::mangleThrowsAnnotation(Node *node) {
   Buffer << 'K';
 }
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index c2a462d..50da198 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -934,7 +934,8 @@
         (void)llvm::sys::fs::remove(pathPair.getKey());
     }
   }
-
+  if (Stats)
+    Stats->noteCurrentProcessExitStatus(result);
   return result;
 }
 
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a32e4d9..336feda 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1414,8 +1414,9 @@
       }
       case types::TY_SwiftModuleFile:
       case types::TY_SwiftModuleDocFile:
-        if (OI.ShouldGenerateModule) {
-          // When generating a .swiftmodule, treat .swiftmodule files as
+        if (OI.ShouldGenerateModule && !OI.shouldLink()) {
+          // When generating a .swiftmodule as a top-level output (as opposed
+          // to, for example, linking an image), treat .swiftmodule files as
           // inputs to a MergeModule action.
           AllModuleInputs.push_back(Current);
           break;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 8d88e15..2d1e878 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -229,44 +229,48 @@
 
   Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
 
+  if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
+    Opts.VerifyGenericSignaturesInModule = A->getValue();
+  }
+
   // Determine what the user has asked the frontend to do.
   FrontendOptions::ActionType &Action = Opts.RequestedAction;
   if (const Arg *A = Args.getLastArg(OPT_modes_Group)) {
     Option Opt = A->getOption();
     if (Opt.matches(OPT_emit_object)) {
-      Action = FrontendOptions::EmitObject;
+      Action = FrontendOptions::ActionType::EmitObject;
     } else if (Opt.matches(OPT_emit_assembly)) {
-      Action = FrontendOptions::EmitAssembly;
+      Action = FrontendOptions::ActionType::EmitAssembly;
     } else if (Opt.matches(OPT_emit_ir)) {
-      Action = FrontendOptions::EmitIR;
+      Action = FrontendOptions::ActionType::EmitIR;
     } else if (Opt.matches(OPT_emit_bc)) {
-      Action = FrontendOptions::EmitBC;
+      Action = FrontendOptions::ActionType::EmitBC;
     } else if (Opt.matches(OPT_emit_sil)) {
-      Action = FrontendOptions::EmitSIL;
+      Action = FrontendOptions::ActionType::EmitSIL;
     } else if (Opt.matches(OPT_emit_silgen)) {
-      Action = FrontendOptions::EmitSILGen;
+      Action = FrontendOptions::ActionType::EmitSILGen;
     } else if (Opt.matches(OPT_emit_sib)) {
-      Action = FrontendOptions::EmitSIB;
+      Action = FrontendOptions::ActionType::EmitSIB;
     } else if (Opt.matches(OPT_emit_sibgen)) {
-      Action = FrontendOptions::EmitSIBGen;
+      Action = FrontendOptions::ActionType::EmitSIBGen;
     } else if (Opt.matches(OPT_emit_pch)) {
-      Action = FrontendOptions::EmitPCH;
+      Action = FrontendOptions::ActionType::EmitPCH;
     } else if (Opt.matches(OPT_emit_imported_modules)) {
-      Action = FrontendOptions::EmitImportedModules;
+      Action = FrontendOptions::ActionType::EmitImportedModules;
     } else if (Opt.matches(OPT_parse)) {
-      Action = FrontendOptions::Parse;
+      Action = FrontendOptions::ActionType::Parse;
     } else if (Opt.matches(OPT_typecheck)) {
-      Action = FrontendOptions::Typecheck;
+      Action = FrontendOptions::ActionType::Typecheck;
     } else if (Opt.matches(OPT_dump_parse)) {
-      Action = FrontendOptions::DumpParse;
+      Action = FrontendOptions::ActionType::DumpParse;
     } else if (Opt.matches(OPT_dump_ast)) {
-      Action = FrontendOptions::DumpAST;
+      Action = FrontendOptions::ActionType::DumpAST;
     } else if (Opt.matches(OPT_emit_syntax)) {
-      Action = FrontendOptions::EmitSyntax;
+      Action = FrontendOptions::ActionType::EmitSyntax;
     } else if (Opt.matches(OPT_merge_modules)) {
-      Action = FrontendOptions::MergeModules;
+      Action = FrontendOptions::ActionType::MergeModules;
     } else if (Opt.matches(OPT_dump_scope_maps)) {
-      Action = FrontendOptions::DumpScopeMaps;
+      Action = FrontendOptions::ActionType::DumpScopeMaps;
 
       StringRef value = A->getValue();
       if (value == "expanded") {
@@ -296,16 +300,16 @@
           Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
       }
     } else if (Opt.matches(OPT_dump_type_refinement_contexts)) {
-      Action = FrontendOptions::DumpTypeRefinementContexts;
+      Action = FrontendOptions::ActionType::DumpTypeRefinementContexts;
     } else if (Opt.matches(OPT_dump_interface_hash)) {
-      Action = FrontendOptions::DumpInterfaceHash;
+      Action = FrontendOptions::ActionType::DumpInterfaceHash;
     } else if (Opt.matches(OPT_print_ast)) {
-      Action = FrontendOptions::PrintAST;
+      Action = FrontendOptions::ActionType::PrintAST;
     } else if (Opt.matches(OPT_repl) ||
                Opt.matches(OPT_deprecated_integrated_repl)) {
-      Action = FrontendOptions::REPL;
+      Action = FrontendOptions::ActionType::REPL;
     } else if (Opt.matches(OPT_interpret)) {
-      Action = FrontendOptions::Immediate;
+      Action = FrontendOptions::ActionType::Immediate;
     } else {
       llvm_unreachable("Unhandled mode option");
     }
@@ -315,11 +319,11 @@
       // We've been told to emit a module, but have no other mode indicators.
       // As a result, put the frontend into EmitModuleOnly mode.
       // (Setting up module output will be handled below.)
-      Action = FrontendOptions::EmitModuleOnly;
+      Action = FrontendOptions::ActionType::EmitModuleOnly;
     }
   }
 
-  if (Opts.RequestedAction == FrontendOptions::Immediate &&
+  if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
       Opts.Inputs.hasPrimaryInput()) {
     Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
     return true;
@@ -331,12 +335,13 @@
   bool TreatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
 
   if (Opts.Inputs.verifyInputs(
-          Diags, TreatAsSIL, Opts.RequestedAction == FrontendOptions::REPL,
-          Opts.RequestedAction == FrontendOptions::NoneAction)) {
+          Diags, TreatAsSIL,
+          Opts.RequestedAction == FrontendOptions::ActionType::REPL,
+          Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
     return true;
   }
 
-  if (Opts.RequestedAction == FrontendOptions::Immediate) {
+  if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
     Opts.ImmediateArgv.push_back(
         Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
     if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
@@ -352,7 +357,7 @@
     Opts.InputKind = InputFileKind::IFK_LLVM_IR;
   else if (Args.hasArg(OPT_parse_as_library))
     Opts.InputKind = InputFileKind::IFK_Swift_Library;
-  else if (Action == FrontendOptions::REPL)
+  else if (Action == FrontendOptions::ActionType::REPL)
     Opts.InputKind = InputFileKind::IFK_Swift_REPL;
   else
     Opts.InputKind = InputFileKind::IFK_Swift;
@@ -372,28 +377,28 @@
 
     StringRef Suffix;
     switch (Opts.RequestedAction) {
-    case FrontendOptions::NoneAction:
+    case FrontendOptions::ActionType::NoneAction:
       break;
 
-    case FrontendOptions::Parse:
-    case FrontendOptions::Typecheck:
-    case FrontendOptions::DumpParse:
-    case FrontendOptions::DumpInterfaceHash:
-    case FrontendOptions::DumpAST:
-    case FrontendOptions::EmitSyntax:
-    case FrontendOptions::PrintAST:
-    case FrontendOptions::DumpScopeMaps:
-    case FrontendOptions::DumpTypeRefinementContexts:
+    case FrontendOptions::ActionType::Parse:
+    case FrontendOptions::ActionType::Typecheck:
+    case FrontendOptions::ActionType::DumpParse:
+    case FrontendOptions::ActionType::DumpInterfaceHash:
+    case FrontendOptions::ActionType::DumpAST:
+    case FrontendOptions::ActionType::EmitSyntax:
+    case FrontendOptions::ActionType::PrintAST:
+    case FrontendOptions::ActionType::DumpScopeMaps:
+    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
       // Textual modes.
       Opts.setOutputFilenameToStdout();
       break;
 
-    case FrontendOptions::EmitPCH:
+    case FrontendOptions::ActionType::EmitPCH:
       Suffix = PCH_EXTENSION;
       break;
 
-    case FrontendOptions::EmitSILGen:
-    case FrontendOptions::EmitSIL: {
+    case FrontendOptions::ActionType::EmitSILGen:
+    case FrontendOptions::ActionType::EmitSIL: {
       if (Opts.OutputFilenames.empty())
         Opts.setOutputFilenameToStdout();
       else
@@ -401,23 +406,23 @@
       break;
     }
 
-    case FrontendOptions::EmitSIBGen:
-    case FrontendOptions::EmitSIB:
+    case FrontendOptions::ActionType::EmitSIBGen:
+    case FrontendOptions::ActionType::EmitSIB:
       Suffix = SIB_EXTENSION;
       break;
 
-    case FrontendOptions::MergeModules:
-    case FrontendOptions::EmitModuleOnly:
+    case FrontendOptions::ActionType::MergeModules:
+    case FrontendOptions::ActionType::EmitModuleOnly:
       Suffix = SERIALIZED_MODULE_EXTENSION;
       break;
 
-    case FrontendOptions::Immediate:
-    case FrontendOptions::REPL:
+    case FrontendOptions::ActionType::Immediate:
+    case FrontendOptions::ActionType::REPL:
       // These modes have no frontend-generated output.
       Opts.OutputFilenames.clear();
       break;
 
-    case FrontendOptions::EmitAssembly: {
+    case FrontendOptions::ActionType::EmitAssembly: {
       if (Opts.OutputFilenames.empty())
         Opts.setOutputFilenameToStdout();
       else
@@ -425,7 +430,7 @@
       break;
     }
 
-    case FrontendOptions::EmitIR: {
+    case FrontendOptions::ActionType::EmitIR: {
       if (Opts.OutputFilenames.empty())
         Opts.setOutputFilenameToStdout();
       else
@@ -433,16 +438,16 @@
       break;
     }
 
-    case FrontendOptions::EmitBC: {
+    case FrontendOptions::ActionType::EmitBC: {
       Suffix = "bc";
       break;
     }
 
-    case FrontendOptions::EmitObject:
+    case FrontendOptions::ActionType::EmitObject:
       Suffix = "o";
       break;
 
-    case FrontendOptions::EmitImportedModules:
+    case FrontendOptions::ActionType::EmitImportedModules:
       if (Opts.OutputFilenames.empty())
         Opts.setOutputFilenameToStdout();
       else
@@ -470,9 +475,9 @@
     }
 
     if (Opts.OutputFilenames.empty()) {
-      if (Opts.RequestedAction != FrontendOptions::REPL &&
-          Opts.RequestedAction != FrontendOptions::Immediate &&
-          Opts.RequestedAction != FrontendOptions::NoneAction) {
+      if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
+          Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
+          Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
         Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
         return true;
       }
@@ -538,16 +543,16 @@
     Opts.FixitsOutputPath = A->getValue();
   }
 
-  bool IsSIB =
-    Opts.RequestedAction == FrontendOptions::EmitSIB ||
-    Opts.RequestedAction == FrontendOptions::EmitSIBGen;
+  bool IsSIB = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB ||
+               Opts.RequestedAction == FrontendOptions::ActionType::EmitSIBGen;
   bool canUseMainOutputForModule =
-    Opts.RequestedAction == FrontendOptions::MergeModules ||
-    Opts.RequestedAction == FrontendOptions::EmitModuleOnly ||
-    IsSIB;
+      Opts.RequestedAction == FrontendOptions::ActionType::MergeModules ||
+      Opts.RequestedAction == FrontendOptions::ActionType::EmitModuleOnly ||
+      IsSIB;
   auto ext = IsSIB ? SIB_EXTENSION : SERIALIZED_MODULE_EXTENSION;
-  auto sibOpt = Opts.RequestedAction == FrontendOptions::EmitSIB ?
-    OPT_emit_sib : OPT_emit_sibgen;
+  auto sibOpt = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB
+                    ? OPT_emit_sib
+                    : OPT_emit_sibgen;
   determineOutputFilename(Opts.ModuleOutputPath,
                           IsSIB ? sibOpt : OPT_emit_module,
                           OPT_emit_module_path,
@@ -562,97 +567,97 @@
 
   if (!Opts.DependenciesFilePath.empty()) {
     switch (Opts.RequestedAction) {
-    case FrontendOptions::NoneAction:
-    case FrontendOptions::DumpParse:
-    case FrontendOptions::DumpInterfaceHash:
-    case FrontendOptions::DumpAST:
-    case FrontendOptions::EmitSyntax:
-    case FrontendOptions::PrintAST:
-    case FrontendOptions::DumpScopeMaps:
-    case FrontendOptions::DumpTypeRefinementContexts:
-    case FrontendOptions::Immediate:
-    case FrontendOptions::REPL:
+    case FrontendOptions::ActionType::NoneAction:
+    case FrontendOptions::ActionType::DumpParse:
+    case FrontendOptions::ActionType::DumpInterfaceHash:
+    case FrontendOptions::ActionType::DumpAST:
+    case FrontendOptions::ActionType::EmitSyntax:
+    case FrontendOptions::ActionType::PrintAST:
+    case FrontendOptions::ActionType::DumpScopeMaps:
+    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+    case FrontendOptions::ActionType::Immediate:
+    case FrontendOptions::ActionType::REPL:
       Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
       return true;
-    case FrontendOptions::Parse:
-    case FrontendOptions::Typecheck:
-    case FrontendOptions::MergeModules:
-    case FrontendOptions::EmitModuleOnly:
-    case FrontendOptions::EmitPCH:
-    case FrontendOptions::EmitSILGen:
-    case FrontendOptions::EmitSIL:
-    case FrontendOptions::EmitSIBGen:
-    case FrontendOptions::EmitSIB:
-    case FrontendOptions::EmitIR:
-    case FrontendOptions::EmitBC:
-    case FrontendOptions::EmitAssembly:
-    case FrontendOptions::EmitObject:
-    case FrontendOptions::EmitImportedModules:
+    case FrontendOptions::ActionType::Parse:
+    case FrontendOptions::ActionType::Typecheck:
+    case FrontendOptions::ActionType::MergeModules:
+    case FrontendOptions::ActionType::EmitModuleOnly:
+    case FrontendOptions::ActionType::EmitPCH:
+    case FrontendOptions::ActionType::EmitSILGen:
+    case FrontendOptions::ActionType::EmitSIL:
+    case FrontendOptions::ActionType::EmitSIBGen:
+    case FrontendOptions::ActionType::EmitSIB:
+    case FrontendOptions::ActionType::EmitIR:
+    case FrontendOptions::ActionType::EmitBC:
+    case FrontendOptions::ActionType::EmitAssembly:
+    case FrontendOptions::ActionType::EmitObject:
+    case FrontendOptions::ActionType::EmitImportedModules:
       break;
     }
   }
 
   if (!Opts.ObjCHeaderOutputPath.empty()) {
     switch (Opts.RequestedAction) {
-    case FrontendOptions::NoneAction:
-    case FrontendOptions::DumpParse:
-    case FrontendOptions::DumpInterfaceHash:
-    case FrontendOptions::DumpAST:
-    case FrontendOptions::EmitSyntax:
-    case FrontendOptions::PrintAST:
-    case FrontendOptions::EmitPCH:
-    case FrontendOptions::DumpScopeMaps:
-    case FrontendOptions::DumpTypeRefinementContexts:
-    case FrontendOptions::Immediate:
-    case FrontendOptions::REPL:
+    case FrontendOptions::ActionType::NoneAction:
+    case FrontendOptions::ActionType::DumpParse:
+    case FrontendOptions::ActionType::DumpInterfaceHash:
+    case FrontendOptions::ActionType::DumpAST:
+    case FrontendOptions::ActionType::EmitSyntax:
+    case FrontendOptions::ActionType::PrintAST:
+    case FrontendOptions::ActionType::EmitPCH:
+    case FrontendOptions::ActionType::DumpScopeMaps:
+    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+    case FrontendOptions::ActionType::Immediate:
+    case FrontendOptions::ActionType::REPL:
       Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
       return true;
-    case FrontendOptions::Parse:
-    case FrontendOptions::Typecheck:
-    case FrontendOptions::MergeModules:
-    case FrontendOptions::EmitModuleOnly:
-    case FrontendOptions::EmitSILGen:
-    case FrontendOptions::EmitSIL:
-    case FrontendOptions::EmitSIBGen:
-    case FrontendOptions::EmitSIB:
-    case FrontendOptions::EmitIR:
-    case FrontendOptions::EmitBC:
-    case FrontendOptions::EmitAssembly:
-    case FrontendOptions::EmitObject:
-    case FrontendOptions::EmitImportedModules:
+    case FrontendOptions::ActionType::Parse:
+    case FrontendOptions::ActionType::Typecheck:
+    case FrontendOptions::ActionType::MergeModules:
+    case FrontendOptions::ActionType::EmitModuleOnly:
+    case FrontendOptions::ActionType::EmitSILGen:
+    case FrontendOptions::ActionType::EmitSIL:
+    case FrontendOptions::ActionType::EmitSIBGen:
+    case FrontendOptions::ActionType::EmitSIB:
+    case FrontendOptions::ActionType::EmitIR:
+    case FrontendOptions::ActionType::EmitBC:
+    case FrontendOptions::ActionType::EmitAssembly:
+    case FrontendOptions::ActionType::EmitObject:
+    case FrontendOptions::ActionType::EmitImportedModules:
       break;
     }
   }
 
   if (!Opts.LoadedModuleTracePath.empty()) {
     switch (Opts.RequestedAction) {
-    case FrontendOptions::NoneAction:
-    case FrontendOptions::Parse:
-    case FrontendOptions::DumpParse:
-    case FrontendOptions::DumpInterfaceHash:
-    case FrontendOptions::DumpAST:
-    case FrontendOptions::EmitSyntax:
-    case FrontendOptions::PrintAST:
-    case FrontendOptions::DumpScopeMaps:
-    case FrontendOptions::DumpTypeRefinementContexts:
-    case FrontendOptions::Immediate:
-    case FrontendOptions::REPL:
+    case FrontendOptions::ActionType::NoneAction:
+    case FrontendOptions::ActionType::Parse:
+    case FrontendOptions::ActionType::DumpParse:
+    case FrontendOptions::ActionType::DumpInterfaceHash:
+    case FrontendOptions::ActionType::DumpAST:
+    case FrontendOptions::ActionType::EmitSyntax:
+    case FrontendOptions::ActionType::PrintAST:
+    case FrontendOptions::ActionType::DumpScopeMaps:
+    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+    case FrontendOptions::ActionType::Immediate:
+    case FrontendOptions::ActionType::REPL:
       Diags.diagnose(SourceLoc(),
                      diag::error_mode_cannot_emit_loaded_module_trace);
       return true;
-    case FrontendOptions::Typecheck:
-    case FrontendOptions::MergeModules:
-    case FrontendOptions::EmitModuleOnly:
-    case FrontendOptions::EmitPCH:
-    case FrontendOptions::EmitSILGen:
-    case FrontendOptions::EmitSIL:
-    case FrontendOptions::EmitSIBGen:
-    case FrontendOptions::EmitSIB:
-    case FrontendOptions::EmitIR:
-    case FrontendOptions::EmitBC:
-    case FrontendOptions::EmitAssembly:
-    case FrontendOptions::EmitObject:
-    case FrontendOptions::EmitImportedModules:
+    case FrontendOptions::ActionType::Typecheck:
+    case FrontendOptions::ActionType::MergeModules:
+    case FrontendOptions::ActionType::EmitModuleOnly:
+    case FrontendOptions::ActionType::EmitPCH:
+    case FrontendOptions::ActionType::EmitSILGen:
+    case FrontendOptions::ActionType::EmitSIL:
+    case FrontendOptions::ActionType::EmitSIBGen:
+    case FrontendOptions::ActionType::EmitSIB:
+    case FrontendOptions::ActionType::EmitIR:
+    case FrontendOptions::ActionType::EmitBC:
+    case FrontendOptions::ActionType::EmitAssembly:
+    case FrontendOptions::ActionType::EmitObject:
+    case FrontendOptions::ActionType::EmitImportedModules:
       break;
     }
   }
@@ -660,35 +665,35 @@
   if (!Opts.ModuleOutputPath.empty() ||
       !Opts.ModuleDocOutputPath.empty()) {
     switch (Opts.RequestedAction) {
-    case FrontendOptions::NoneAction:
-    case FrontendOptions::Parse:
-    case FrontendOptions::Typecheck:
-    case FrontendOptions::DumpParse:
-    case FrontendOptions::DumpInterfaceHash:
-    case FrontendOptions::DumpAST:
-    case FrontendOptions::EmitSyntax:
-    case FrontendOptions::PrintAST:
-    case FrontendOptions::EmitPCH:
-    case FrontendOptions::DumpScopeMaps:
-    case FrontendOptions::DumpTypeRefinementContexts:
-    case FrontendOptions::EmitSILGen:
-    case FrontendOptions::Immediate:
-    case FrontendOptions::REPL:
+    case FrontendOptions::ActionType::NoneAction:
+    case FrontendOptions::ActionType::Parse:
+    case FrontendOptions::ActionType::Typecheck:
+    case FrontendOptions::ActionType::DumpParse:
+    case FrontendOptions::ActionType::DumpInterfaceHash:
+    case FrontendOptions::ActionType::DumpAST:
+    case FrontendOptions::ActionType::EmitSyntax:
+    case FrontendOptions::ActionType::PrintAST:
+    case FrontendOptions::ActionType::EmitPCH:
+    case FrontendOptions::ActionType::DumpScopeMaps:
+    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+    case FrontendOptions::ActionType::EmitSILGen:
+    case FrontendOptions::ActionType::Immediate:
+    case FrontendOptions::ActionType::REPL:
       if (!Opts.ModuleOutputPath.empty())
         Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
       else
         Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
       return true;
-    case FrontendOptions::MergeModules:
-    case FrontendOptions::EmitModuleOnly:
-    case FrontendOptions::EmitSIL:
-    case FrontendOptions::EmitSIBGen:
-    case FrontendOptions::EmitSIB:
-    case FrontendOptions::EmitIR:
-    case FrontendOptions::EmitBC:
-    case FrontendOptions::EmitAssembly:
-    case FrontendOptions::EmitObject:
-    case FrontendOptions::EmitImportedModules:
+    case FrontendOptions::ActionType::MergeModules:
+    case FrontendOptions::ActionType::EmitModuleOnly:
+    case FrontendOptions::ActionType::EmitSIL:
+    case FrontendOptions::ActionType::EmitSIBGen:
+    case FrontendOptions::ActionType::EmitSIB:
+    case FrontendOptions::ActionType::EmitIR:
+    case FrontendOptions::ActionType::EmitBC:
+    case FrontendOptions::ActionType::EmitAssembly:
+    case FrontendOptions::ActionType::EmitObject:
+    case FrontendOptions::ActionType::EmitImportedModules:
       break;
     }
   }
@@ -1165,8 +1170,7 @@
     Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
         A->getOption().getPrefixedName(), A->getValue());
   }
-  if (Opts.Optimization > SILOptions::SILOptMode::None
-      && Opts.EnforceExclusivityDynamic) {
+  if (Opts.shouldOptimize() && Opts.EnforceExclusivityDynamic) {
     Diags.diagnose(SourceLoc(),
                    diag::warning_argument_not_supported_with_optimization,
                    A->getOption().getPrefixedName() + A->getValue());
@@ -1225,40 +1229,31 @@
 
   // Parse the optimization level.
   // Default to Onone settings if no option is passed.
-  IRGenOpts.Optimize = false;
-  IRGenOpts.OptimizeForSize = false;
-  Opts.Optimization = SILOptions::SILOptMode::None;
+  Opts.OptMode = OptimizationMode::NoOptimization;
   if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
     if (A->getOption().matches(OPT_Onone)) {
       // Already set.
     } else if (A->getOption().matches(OPT_Ounchecked)) {
       // Turn on optimizations and remove all runtime checks.
-      IRGenOpts.Optimize = true;
-      IRGenOpts.OptimizeForSize = false;
-      Opts.Optimization = SILOptions::SILOptMode::OptimizeUnchecked;
+      Opts.OptMode = OptimizationMode::ForSpeed;
       // Removal of cond_fail (overflow on binary operations).
       Opts.RemoveRuntimeAsserts = true;
       Opts.AssertConfig = SILOptions::Unchecked;
     } else if (A->getOption().matches(OPT_Oplayground)) {
       // For now -Oplayground is equivalent to -Onone.
-      IRGenOpts.Optimize = false;
-      IRGenOpts.OptimizeForSize = false;
-      Opts.Optimization = SILOptions::SILOptMode::None;
+      Opts.OptMode = OptimizationMode::NoOptimization;
     } else if (A->getOption().matches(OPT_Osize)) {
-      IRGenOpts.Optimize = true;
-      IRGenOpts.OptimizeForSize = true;
-      Opts.Optimization = SILOptions::SILOptMode::OptimizeForSize;
+      Opts.OptMode = OptimizationMode::ForSize;
     } else {
       assert(A->getOption().matches(OPT_O));
-      IRGenOpts.OptimizeForSize = false;
-      IRGenOpts.Optimize = true;
-      Opts.Optimization = SILOptions::SILOptMode::Optimize;
+      Opts.OptMode = OptimizationMode::ForSpeed;
     }
 
-    if (IRGenOpts.Optimize) {
+    if (Opts.shouldOptimize()) {
       ClangOpts.Optimization = "-Os";
     }
   }
+  IRGenOpts.OptMode = Opts.OptMode;
 
   if (Args.getLastArg(OPT_AssumeSingleThreaded)) {
     Opts.AssumeSingleThreaded = true;
@@ -1288,7 +1283,7 @@
     // Set the assert configuration according to the optimization level if it
     // has not been set by the -Ounchecked flag.
     Opts.AssertConfig =
-        IRGenOpts.Optimize ? SILOptions::Release : SILOptions::Debug;
+        (IRGenOpts.shouldOptimize() ? SILOptions::Release : SILOptions::Debug);
   }
 
   // -Ounchecked might also set removal of runtime asserts (cond_fail).
@@ -1345,7 +1340,7 @@
     IRGenOpts.Sanitizers = Opts.Sanitizers;
   }
 
-  if (Opts.Optimization > SILOptions::SILOptMode::None)
+  if (Opts.shouldOptimize())
     Opts.EnforceExclusivityDynamic = false;
   if (const Arg *A = Args.getLastArg(options::OPT_enforce_exclusivity_EQ)) {
     parseExclusivityEnforcementOptions(A, Opts, Diags);
@@ -1703,3 +1698,39 @@
                         extendedInfo.getExtraClangImporterOptions().end());
   return info.status;
 }
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+CompilerInvocation::setUpInputForSILTool(
+    StringRef InputFilename, StringRef ModuleNameArg,
+    bool alwaysSetModuleToMain,
+    serialization::ExtendedValidationInfo &extendedInfo) {
+  // Load the input file.
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
+      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+  if (!FileBufOrErr) {
+    return FileBufOrErr;
+  }
+
+  // If it looks like we have an AST, set the source file kind to SIL and the
+  // name of the module to the file's name.
+  addInputBuffer(FileBufOrErr.get().get());
+
+  auto result = serialization::validateSerializedAST(
+      FileBufOrErr.get()->getBuffer(), &extendedInfo);
+  bool HasSerializedAST = result.status == serialization::Status::Valid;
+
+  if (HasSerializedAST) {
+    const StringRef Stem = !ModuleNameArg.empty()
+                               ? ModuleNameArg
+                               : llvm::sys::path::stem(InputFilename);
+    setModuleName(Stem);
+    setInputKind(InputFileKind::IFK_Swift_Library);
+  } else {
+    const StringRef Name = (alwaysSetModuleToMain || ModuleNameArg.empty())
+                               ? "main"
+                               : ModuleNameArg;
+    setModuleName(Name);
+    setInputKind(InputFileKind::IFK_SIL);
+  }
+  return FileBufOrErr;
+}
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index ff1791c..344595c 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -257,14 +257,14 @@
   if (Invocation.getImplicitModuleImportKind() !=
       SourceFile::ImplicitModuleImportKind::Stdlib)
     return false;
-  SILOptions::SILOptMode optimization = Invocation.getSILOptions().Optimization;
-  if (optimization <= SILOptions::SILOptMode::None &&
-      shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
+  if (Invocation.getSILOptions().shouldOptimize())
+    return false;
+
+  if (shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
           Invocation.getFrontendOptions().RequestedAction)) {
     return true;
   }
-  return optimization == SILOptions::SILOptMode::None &&
-         Invocation.getFrontendOptions().isCreatingSIL();
+  return Invocation.getFrontendOptions().isCreatingSIL();
 }
 
 void CompilerInstance::performSema() {
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index c9cbe96..8bdca8f 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -170,33 +170,33 @@
 
 bool FrontendOptions::actionHasOutput() const {
   switch (RequestedAction) {
-  case NoneAction:
-  case Parse:
-  case Typecheck:
-  case DumpParse:
-  case DumpAST:
-  case EmitSyntax:
-  case DumpInterfaceHash:
-  case PrintAST:
-  case DumpScopeMaps:
-  case DumpTypeRefinementContexts:
+  case ActionType::NoneAction:
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
     return false;
-  case EmitPCH:
-  case EmitSILGen:
-  case EmitSIL:
-  case EmitSIBGen:
-  case EmitSIB:
-  case EmitModuleOnly:
-  case MergeModules:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitModuleOnly:
+  case ActionType::MergeModules:
     return true;
-  case Immediate:
-  case REPL:
+  case ActionType::Immediate:
+  case ActionType::REPL:
     return false;
-  case EmitAssembly:
-  case EmitIR:
-  case EmitBC:
-  case EmitObject:
-  case EmitImportedModules:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
     return true;
   }
   llvm_unreachable("Unknown ActionType");
@@ -204,32 +204,32 @@
 
 bool FrontendOptions::actionIsImmediate() const {
   switch (RequestedAction) {
-  case NoneAction:
-  case Parse:
-  case Typecheck:
-  case DumpParse:
-  case DumpAST:
-  case EmitSyntax:
-  case DumpInterfaceHash:
-  case PrintAST:
-  case DumpScopeMaps:
-  case DumpTypeRefinementContexts:
-  case EmitPCH:
-  case EmitSILGen:
-  case EmitSIL:
-  case EmitSIBGen:
-  case EmitSIB:
-  case EmitModuleOnly:
-  case MergeModules:
+  case ActionType::NoneAction:
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitModuleOnly:
+  case ActionType::MergeModules:
     return false;
-  case Immediate:
-  case REPL:
+  case ActionType::Immediate:
+  case ActionType::REPL:
     return true;
-  case EmitAssembly:
-  case EmitIR:
-  case EmitBC:
-  case EmitObject:
-  case EmitImportedModules:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
     return false;
   }
   llvm_unreachable("Unknown ActionType");
@@ -237,8 +237,8 @@
 
 void FrontendOptions::forAllOutputPaths(
     std::function<void(const std::string &)> fn) const {
-  if (RequestedAction != FrontendOptions::EmitModuleOnly &&
-      RequestedAction != FrontendOptions::MergeModules) {
+  if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
+      RequestedAction != FrontendOptions::ActionType::MergeModules) {
     for (const std::string &OutputFileName : OutputFilenames) {
       fn(OutputFileName);
     }
@@ -299,7 +299,7 @@
   // Note: this code path will only be taken when running the frontend
   // directly; the driver should always pass -module-name when invoking the
   // frontend.
-  if (RequestedAction == FrontendOptions::REPL) {
+  if (RequestedAction == FrontendOptions::ActionType::REPL) {
     // Default to a module named "REPL" if we're in REPL mode.
     return "REPL";
   }
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index fba8441..d6acb03 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -30,6 +30,7 @@
 #include "swift/AST/ASTScope.h"
 #include "swift/AST/DiagnosticsFrontend.h"
 #include "swift/AST/DiagnosticsSema.h"
+#include "swift/AST/GenericSignatureBuilder.h"
 #include "swift/AST/IRGenOptions.h"
 #include "swift/AST/ASTMangler.h"
 #include "swift/AST/LegacyASTTransformer.h"
@@ -58,6 +59,7 @@
 #include "swift/Serialization/SerializedModuleLoader.h"
 #include "swift/SILOptimizer/PassManager/Passes.h"
 #include "swift/Syntax/Serialization/SyntaxSerialization.h"
+#include "swift/Syntax/SyntaxNodes.h"
 
 // FIXME: We're just using CompilerInstance::createOutputFile.
 // This API should be sunk down to LLVM.
@@ -255,38 +257,12 @@
   assert(bufferID && "frontend should have a buffer ID "
          "for the main source file");
 
-  // Get a full token stream with associated Trivia.
-  syntax::TokenPositionList tokens =
-    tokenizeWithTrivia(LangOpts, SM, *bufferID);
-
-  llvm::SmallVector<Decl *, 16> topLevelDecls;
-  SF->getTopLevelDecls(topLevelDecls);
-
-  // Convert the old ASTs to the Syntax tree and print
-  // them out.
-  SyntaxASTMap ASTMap;
-  std::vector<RC<syntax::RawSyntax>> topLevelRaw;
-  for (auto *decl : topLevelDecls) {
-    if (decl->escapedFromIfConfig()) {
-      continue;
-    }
-    auto newNode = transformAST(ASTNode(decl), ASTMap, SM, *bufferID, tokens);
-    if (newNode.hasValue()) {
-      topLevelRaw.push_back(newNode->getRaw());
-    }
-  }
-
-  // Push the EOF token -- this ensures that any remaining trivia in the
-  // file is serialized as the EOF's leading trivia.
-  if (!tokens.empty() && tokens.back().first->getTokenKind() == tok::eof) {
-    topLevelRaw.push_back(tokens.back().first);
-  }
-
   auto os = getFileOutputStream(OutputFilename, SF->getASTContext());
   if (!os) return true;
 
   json::Output jsonOut(*os);
-  jsonOut << topLevelRaw;
+  auto Root = SF->getSyntaxRoot().getRaw();
+  jsonOut << Root;
   *os << "\n";
   return false;
 }
@@ -343,15 +319,15 @@
 /// Returns the OutputKind for the given Action.
 static IRGenOutputKind getOutputKind(FrontendOptions::ActionType Action) {
   switch (Action) {
-  case FrontendOptions::EmitIR:
+  case FrontendOptions::ActionType::EmitIR:
     return IRGenOutputKind::LLVMAssembly;
-  case FrontendOptions::EmitBC:
+  case FrontendOptions::ActionType::EmitBC:
     return IRGenOutputKind::LLVMBitcode;
-  case FrontendOptions::EmitAssembly:
+  case FrontendOptions::ActionType::EmitAssembly:
     return IRGenOutputKind::NativeAssembly;
-  case FrontendOptions::EmitObject:
+  case FrontendOptions::ActionType::EmitObject:
     return IRGenOutputKind::ObjectFile;
-  case FrontendOptions::Immediate:
+  case FrontendOptions::ActionType::Immediate:
     return IRGenOutputKind::Module;
   default:
     llvm_unreachable("Unknown ActionType which requires IRGen");
@@ -536,9 +512,12 @@
   FrontendOptions opts = Invocation.getFrontendOptions();
   FrontendOptions::ActionType Action = opts.RequestedAction;
 
+  if (Action == FrontendOptions::ActionType::EmitSyntax)
+    Instance.getASTContext().LangOpts.KeepSyntaxInfoInSourceFile = true;
+
   // We've been asked to precompile a bridging header; we want to
   // avoid touching any other inputs and just parse, emit and exit.
-  if (Action == FrontendOptions::EmitPCH) {
+  if (Action == FrontendOptions::ActionType::EmitPCH) {
     auto clangImporter = static_cast<ClangImporter *>(
       Instance.getASTContext().getClangModuleLoader());
     auto &ImporterOpts = Invocation.getClangImporterOptions();
@@ -602,16 +581,16 @@
   if (shouldTrackReferences)
     Instance.setReferencedNameTracker(&nameTracker);
 
-  if (Action == FrontendOptions::Parse ||
-      Action == FrontendOptions::DumpParse ||
-      Action == FrontendOptions::EmitSyntax ||
-      Action == FrontendOptions::DumpInterfaceHash ||
-      Action == FrontendOptions::EmitImportedModules)
+  if (Action == FrontendOptions::ActionType::Parse ||
+      Action == FrontendOptions::ActionType::DumpParse ||
+      Action == FrontendOptions::ActionType::EmitSyntax ||
+      Action == FrontendOptions::ActionType::DumpInterfaceHash ||
+      Action == FrontendOptions::ActionType::EmitImportedModules)
     Instance.performParseOnly();
   else
     Instance.performSema();
 
-  if (Action == FrontendOptions::Parse)
+  if (Action == FrontendOptions::ActionType::Parse)
     return Instance.getASTContext().hadError();
 
   if (observer) {
@@ -630,11 +609,19 @@
 
   ASTContext &Context = Instance.getASTContext();
 
+
+  auto verifyGenericSignaturesInModule =
+    Invocation.getFrontendOptions().VerifyGenericSignaturesInModule;
+  if (!verifyGenericSignaturesInModule.empty()) {
+    if (auto module = Context.getModuleByName(verifyGenericSignaturesInModule))
+      GenericSignatureBuilder::verifyGenericSignaturesInModule(module);
+  }
+
   if (Invocation.getMigratorOptions().shouldRunMigrator()) {
     migrator::updateCodeAndEmitRemap(&Instance, Invocation);
   }
 
-  if (Action == FrontendOptions::REPL) {
+  if (Action == FrontendOptions::ActionType::REPL) {
     runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()),
             Invocation.getParseStdlib());
     return Context.hadError();
@@ -645,21 +632,21 @@
   // We've been told to dump the AST (either after parsing or type-checking,
   // which is already differentiated in CompilerInstance::performSema()),
   // so dump or print the main source file and return.
-  if (Action == FrontendOptions::DumpParse ||
-      Action == FrontendOptions::DumpAST ||
-      Action == FrontendOptions::EmitSyntax ||
-      Action == FrontendOptions::PrintAST ||
-      Action == FrontendOptions::DumpScopeMaps ||
-      Action == FrontendOptions::DumpTypeRefinementContexts ||
-      Action == FrontendOptions::DumpInterfaceHash) {
+  if (Action == FrontendOptions::ActionType::DumpParse ||
+      Action == FrontendOptions::ActionType::DumpAST ||
+      Action == FrontendOptions::ActionType::EmitSyntax ||
+      Action == FrontendOptions::ActionType::PrintAST ||
+      Action == FrontendOptions::ActionType::DumpScopeMaps ||
+      Action == FrontendOptions::ActionType::DumpTypeRefinementContexts ||
+      Action == FrontendOptions::ActionType::DumpInterfaceHash) {
     SourceFile *SF = PrimarySourceFile;
     if (!SF) {
       SourceFileKind Kind = Invocation.getSourceFileKind();
       SF = &Instance.getMainModule()->getMainSourceFile(Kind);
     }
-    if (Action == FrontendOptions::PrintAST)
+    if (Action == FrontendOptions::ActionType::PrintAST)
       SF->print(llvm::outs(), PrintOptions::printEverything());
-    else if (Action == FrontendOptions::DumpScopeMaps) {
+    else if (Action == FrontendOptions::ActionType::DumpScopeMaps) {
       ASTScope &scope = SF->getScope();
 
       if (opts.DumpScopeMapLocations.empty()) {
@@ -703,17 +690,18 @@
 
       // Print the resulting map.
       scope.print(llvm::errs());
-    } else if (Action == FrontendOptions::DumpTypeRefinementContexts)
+    } else if (Action ==
+               FrontendOptions::ActionType::DumpTypeRefinementContexts)
       SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr);
-    else if (Action == FrontendOptions::DumpInterfaceHash)
+    else if (Action == FrontendOptions::ActionType::DumpInterfaceHash)
       SF->dumpInterfaceHash(llvm::errs());
-    else if (Action == FrontendOptions::EmitSyntax) {
+    else if (Action == FrontendOptions::ActionType::EmitSyntax) {
       emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
                  opts.getSingleOutputFilename());
     } else
       SF->dump();
     return Context.hadError();
-  } else if (Action == FrontendOptions::EmitImportedModules) {
+  } else if (Action == FrontendOptions::ActionType::EmitImportedModules) {
     emitImportedModules(Context, Instance.getMainModule(), opts);
     return Context.hadError();
   }
@@ -753,7 +741,7 @@
       !Context.LangOpts.EnableAppExtensionRestrictions;
 
   // We've just been told to perform a typecheck, so we can return now.
-  if (Action == FrontendOptions::Typecheck) {
+  if (Action == FrontendOptions::ActionType::Typecheck) {
     if (!opts.ObjCHeaderOutputPath.empty())
       return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
                          opts.ImplicitObjCHeaderPath, moduleIsPublic);
@@ -776,7 +764,7 @@
       return true;
   }
 
-  assert(Action >= FrontendOptions::EmitSILGen &&
+  assert(Action >= FrontendOptions::ActionType::EmitSILGen &&
          "All actions not requiring SILGen must have been handled!");
 
   std::unique_ptr<SILModule> SM = Instance.takeSILModule();
@@ -815,7 +803,7 @@
   }
 
   // We've been told to emit SIL after SILGen, so write it now.
-  if (Action == FrontendOptions::EmitSILGen) {
+  if (Action == FrontendOptions::ActionType::EmitSILGen) {
     // If we are asked to link all, link all.
     if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
       performSILLinking(SM.get(), true);
@@ -823,7 +811,7 @@
                     opts.getSingleOutputFilename(), opts.EmitSortedSIL);
   }
 
-  if (Action == FrontendOptions::EmitSIBGen) {
+  if (Action == FrontendOptions::ActionType::EmitSIBGen) {
     // If we are asked to link all, link all.
     if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
       performSILLinking(SM.get(), true);
@@ -849,7 +837,7 @@
                            std::move(OptRecordFile));
 
   // Perform "stable" optimizations that are invariant across compiler versions.
-  if (Action == FrontendOptions::MergeModules) {
+  if (Action == FrontendOptions::ActionType::MergeModules) {
     // Don't run diagnostic passes at all.
   } else if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) {
     if (runSILDiagnosticPasses(*SM))
@@ -921,9 +909,8 @@
   // These may change across compiler versions.
   {
     SharedTimer timer("SIL optimization");
-    if (Action != FrontendOptions::MergeModules &&
-        Invocation.getSILOptions().Optimization >
-          SILOptions::SILOptMode::None) {
+    if (Action != FrontendOptions::ActionType::MergeModules &&
+        Invocation.getSILOptions().shouldOptimize()) {
 
       runSILOptPreparePasses(*SM);
 
@@ -969,7 +956,7 @@
                       opts.ImplicitObjCHeaderPath, moduleIsPublic);
   }
 
-  if (Action == FrontendOptions::EmitSIB) {
+  if (Action == FrontendOptions::ActionType::EmitSIB) {
     auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
                                   Instance.getMainModule();
     if (!opts.ModuleOutputPath.empty()) {
@@ -987,8 +974,8 @@
     // Serialize the SILModule if it was not serialized yet.
     if (!SM.get()->isSerialized())
       SM.get()->serialize();
-    if (Action == FrontendOptions::MergeModules ||
-        Action == FrontendOptions::EmitModuleOnly) {
+    if (Action == FrontendOptions::ActionType::MergeModules ||
+        Action == FrontendOptions::ActionType::EmitModuleOnly) {
       if (shouldIndex) {
         if (emitIndexData(PrimarySourceFile, Invocation, Instance))
           return true;
@@ -997,18 +984,18 @@
     }
   }
 
-  assert(Action >= FrontendOptions::EmitSIL &&
+  assert(Action >= FrontendOptions::ActionType::EmitSIL &&
          "All actions not requiring SILPasses must have been handled!");
 
   // We've been told to write canonical SIL, so write it now.
-  if (Action == FrontendOptions::EmitSIL) {
+  if (Action == FrontendOptions::ActionType::EmitSIL) {
     return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
                     opts.getSingleOutputFilename(), opts.EmitSortedSIL);
   }
 
-  assert(Action >= FrontendOptions::Immediate &&
+  assert(Action >= FrontendOptions::ActionType::Immediate &&
          "All actions not requiring IRGen must have been handled!");
-  assert(Action != FrontendOptions::REPL &&
+  assert(Action != FrontendOptions::ActionType::REPL &&
          "REPL mode must be handled immediately after Instance->performSema()");
 
   // Check if we had any errors; if we did, don't proceed to IRGen.
@@ -1020,7 +1007,7 @@
 
   // TODO: remove once the frontend understands what action it should perform
   IRGenOpts.OutputKind = getOutputKind(Action);
-  if (Action == FrontendOptions::Immediate) {
+  if (Action == FrontendOptions::ActionType::Immediate) {
     assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode");
     IRGenOpts.UseJIT = true;
     IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal;
@@ -1122,15 +1109,13 @@
   // paths as a fallback.
 
   bool isDebugCompilation;
-  switch (Invocation.getSILOptions().Optimization) {
-    case SILOptions::SILOptMode::NotSet:
-    case SILOptions::SILOptMode::None:
-    case SILOptions::SILOptMode::Debug:
+  switch (Invocation.getSILOptions().OptMode) {
+    case OptimizationMode::NotSet:
+    case OptimizationMode::NoOptimization:
       isDebugCompilation = true;
       break;
-    case SILOptions::SILOptMode::Optimize:
-    case SILOptions::SILOptMode::OptimizeForSize:
-    case SILOptions::SILOptMode::OptimizeUnchecked:
+    case OptimizationMode::ForSpeed:
+    case OptimizationMode::ForSize:
       isDebugCompilation = false;
       break;
   }
@@ -1223,13 +1208,11 @@
 }
 
 static StringRef
-silOptModeArgStr(SILOptions::SILOptMode mode) {
+silOptModeArgStr(OptimizationMode mode) {
   switch (mode) {
- case SILOptions::SILOptMode::Optimize:
+ case OptimizationMode::ForSpeed:
    return "O";
- case SILOptions::SILOptMode::OptimizeUnchecked:
-   return "Ounchecked";
- case SILOptions::SILOptMode::OptimizeForSize:
+ case OptimizationMode::ForSize:
    return "Osize";
  default:
    return "Onone";
@@ -1339,7 +1322,7 @@
   }
 
   if (Invocation.getFrontendOptions().RequestedAction ==
-        FrontendOptions::NoneAction) {
+      FrontendOptions::ActionType::NoneAction) {
     Instance->getDiags().diagnose(SourceLoc(),
                                  diag::error_missing_frontend_action);
     return finishDiagProcessing(1);
@@ -1391,7 +1374,7 @@
     auto &LangOpts = Invocation.getLangOptions();
     auto &SILOpts = Invocation.getSILOptions();
     StringRef InputName = FEOpts.Inputs.primaryInputFilenameIfAny();
-    StringRef OptType = silOptModeArgStr(SILOpts.Optimization);
+    StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
     StringRef OutFile = FEOpts.getSingleOutputFilename();
     StringRef OutputType = llvm::sys::path::extension(OutFile);
     std::string TripleName = LangOpts.Target.normalize();
@@ -1467,7 +1450,10 @@
     }
   }
 
-  return finishDiagProcessing(HadError ? 1 : ReturnValue);
+  auto r = finishDiagProcessing(HadError ? 1 : ReturnValue);
+  if (StatsReporter)
+    StatsReporter->noteCurrentProcessExitStatus(r);
+  return r;
 }
 
 void FrontendObserver::parsedArgs(CompilerInvocation &invocation) {}
diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt
index 90ec65a..e93742f 100644
--- a/lib/IDE/CMakeLists.txt
+++ b/lib/IDE/CMakeLists.txt
@@ -12,6 +12,7 @@
   Utils.cpp
   IDETypeChecking.cpp
   APIDigesterData.cpp
+  SourceEntityWalker.cpp
   DEPENDS
     swift-syntax-generated-headers
   LINK_LIBRARIES
diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp
index 8a9c6e7..5b0059e 100644
--- a/lib/IDE/Formatting.cpp
+++ b/lib/IDE/Formatting.cpp
@@ -11,7 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Parse/Parser.h"
 #include "swift/Frontend/Frontend.h"
 #include "swift/Basic/SourceManager.h"
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index aa49de2..b61ca6d 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -819,7 +819,7 @@
 
   // We cannot extract expressions of l-value type.
   if (auto Ty = RangeInfo.getType()) {
-    if (Ty->hasLValueType() || Ty->getKind() == TypeKind::InOut)
+    if (Ty->hasLValueType() || Ty->is<InOutType>())
       return ExtractCheckResult();
 
     // Disallow extracting error type expressions/statements
@@ -886,6 +886,7 @@
   switch (Info.Kind) {
   case RangeKind::PartOfExpression:
   case RangeKind::SingleDecl:
+  case RangeKind::MultiTypeMemberDecl:
   case RangeKind::Invalid:
     return false;
   case RangeKind::SingleExpression:
@@ -940,7 +941,7 @@
 static Type sanitizeType(Type Ty) {
   // Transform lvalue type to inout type so that we can print it properly.
   return Ty.transform([](Type Ty) {
-    if (Ty->getKind() == TypeKind::LValue) {
+    if (Ty->is<LValueType>()) {
       return Type(InOutType::get(Ty->getRValueType()->getCanonicalType()));
     }
     return Ty;
@@ -1162,7 +1163,7 @@
     for (auto &RD : Parameters) {
 
       // Inout argument needs "&".
-      if (RD.Ty->getKind() == TypeKind::InOut)
+      if (RD.Ty->is<InOutType>())
         OS << "&";
       OS << RD.VD->getBaseName().userFacingName();
       if (&RD != &Parameters.back())
@@ -1420,6 +1421,7 @@
       return checkExtractConditions(Info, Diag).success();
     case RangeKind::PartOfExpression:
     case RangeKind::SingleDecl:
+    case RangeKind::MultiTypeMemberDecl:
     case RangeKind::SingleStatement:
     case RangeKind::MultiStatement:
     case RangeKind::Invalid:
@@ -1441,6 +1443,7 @@
         success({CannotExtractReason::Literal});
     case RangeKind::PartOfExpression:
     case RangeKind::SingleDecl:
+    case RangeKind::MultiTypeMemberDecl:
     case RangeKind::SingleStatement:
     case RangeKind::MultiStatement:
     case RangeKind::Invalid:
@@ -1453,6 +1456,82 @@
                                           EditConsumer).performChange();
 }
 
+// Compute a decl context that is the parent context for all decls in
+// \c DeclaredDecls. Return \c nullptr if no such context exists.
+DeclContext *getCommonDeclContext(ArrayRef<DeclaredDecl> DeclaredDecls) {
+  if (DeclaredDecls.empty())
+    return nullptr;
+
+  DeclContext *CommonDC = DeclaredDecls.front().VD->getDeclContext();
+  for (auto DD : DeclaredDecls) {
+    auto OtherDC = DD.VD->getDeclContext();
+    CommonDC = DeclContext::getCommonParentContext(CommonDC, OtherDC);
+  }
+  return CommonDC;
+}
+
+bool RefactoringActionMoveMembersToExtension::isApplicable(
+    ResolvedRangeInfo Info, DiagnosticEngine &Diag) {
+  switch (Info.Kind) {
+  case RangeKind::SingleDecl:
+  case RangeKind::MultiTypeMemberDecl: {
+    DeclContext *CommonDC = getCommonDeclContext(Info.DeclaredDecls);
+
+    // The the common decl context is not a nomial type, we cannot create an
+    // extension for it
+    if (!CommonDC || !CommonDC->getInnermostDeclarationDeclContext() ||
+        !isa<NominalTypeDecl>(CommonDC->getInnermostDeclarationDeclContext()))
+      return false;
+
+    // Members of types not declared at top file level cannot be extracted
+    // to an extension at top file level
+    if (CommonDC->getParent()->getContextKind() != DeclContextKind::FileUnit)
+      return false;
+
+    // We should not move instance variables with storage into the extension
+    // because they are not allowed to be declared there
+    for (auto DD : Info.DeclaredDecls) {
+      if (auto ASD = dyn_cast<AbstractStorageDecl>(DD.VD)) {
+        // Only disallow storages in the common decl context, allow them in
+        // any subtypes
+        if (ASD->hasStorage() && ASD->getDeclContext() == CommonDC) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+  case RangeKind::SingleExpression:
+  case RangeKind::PartOfExpression:
+  case RangeKind::SingleStatement:
+  case RangeKind::MultiStatement:
+  case RangeKind::Invalid:
+    return false;
+  }
+}
+
+bool RefactoringActionMoveMembersToExtension::performChange() {
+  DeclContext *CommonDC = getCommonDeclContext(RangeInfo.DeclaredDecls);
+
+  auto CommonTypeDecl =
+      dyn_cast<NominalTypeDecl>(CommonDC->getInnermostDeclarationDeclContext());
+  assert(CommonTypeDecl && "Not applicable if common parent is no nomial type");
+
+  SmallString<64> Buffer;
+  llvm::raw_svector_ostream OS(Buffer);
+  OS << "\n\n";
+  OS << "extension " << CommonTypeDecl->getName() << " {\n";
+  OS << RangeInfo.ContentRange.str().trim();
+  OS << "\n}";
+
+  // Insert extension after the type declaration
+  EditConsumer.insertAfter(SM, CommonTypeDecl->getEndLoc(), Buffer);
+  EditConsumer.remove(SM, RangeInfo.ContentRange);
+
+  return false;
+}
+
 struct CollapsibleNestedIfInfo {
   IfStmt *OuterIf;
   IfStmt *InnerIf;
@@ -2268,6 +2347,7 @@
       return false;
     }
     case RangeKind::SingleDecl:
+    case RangeKind::MultiTypeMemberDecl:
     case RangeKind::SingleStatement:
     case RangeKind::MultiStatement:
     case RangeKind::Invalid:
diff --git a/lib/AST/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp
similarity index 94%
rename from lib/AST/SourceEntityWalker.cpp
rename to lib/IDE/SourceEntityWalker.cpp
index 7b04710..6622bb9 100644
--- a/lib/AST/SourceEntityWalker.cpp
+++ b/lib/IDE/SourceEntityWalker.cpp
@@ -10,7 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Parse/Lexer.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ASTWalker.h"
@@ -65,7 +65,9 @@
   bool passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data);
   bool passReference(ModuleEntity Mod, std::pair<Identifier, SourceLoc> IdLoc);
 
-  bool passSubscriptReference(ValueDecl *D, SourceLoc Loc, bool IsOpenBracket);
+  bool passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+                              Optional<AccessKind> AccKind,
+                              bool IsOpenBracket);
 
   bool passCallArgNames(Expr *Fn, TupleExpr *TupleE);
 
@@ -297,7 +299,7 @@
       SubscrD = SE->getDecl().getDecl();
 
     if (SubscrD) {
-      if (!passSubscriptReference(SubscrD, E->getLoc(), true))
+      if (!passSubscriptReference(SubscrD, E->getLoc(), OpAccess, true))
         return { false, nullptr };
     }
 
@@ -305,7 +307,7 @@
       return { false, nullptr };
 
     if (SubscrD) {
-      if (!passSubscriptReference(SubscrD, E->getEndLoc(), false))
+      if (!passSubscriptReference(SubscrD, E->getEndLoc(), OpAccess, false))
         return { false, nullptr };
     }
 
@@ -434,12 +436,14 @@
 }
 
 bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+                                           Optional<AccessKind> AccKind,
                                            bool IsOpenBracket) {
   CharSourceRange Range = Loc.isValid()
                         ? CharSourceRange(Loc, 1)
                         : CharSourceRange();
 
-  bool Continue = SEWalker.visitSubscriptReference(D, Range, IsOpenBracket);
+  bool Continue = SEWalker.visitSubscriptReference(D, Range, AccKind,
+                                                   IsOpenBracket);
   if (!Continue)
     Cancelled = true;
   return Continue;
@@ -556,6 +560,17 @@
   return DC->walkContext(Annotator);
 }
 
+bool SourceEntityWalker::walk(ASTNode N) {
+  if (auto *E = N.dyn_cast<Expr*>())
+    return walk(E);
+  if (auto *S = N.dyn_cast<Stmt*>())
+    return walk(S);
+  if (auto *D = N.dyn_cast<Decl*>())
+    return walk(D);
+
+  llvm_unreachable("unsupported AST node");
+}
+
 bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range,
                                             TypeDecl *CtorTyRef,
                                             ExtensionDecl *ExtTyRef, Type T,
@@ -565,12 +580,13 @@
 
 bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
                                                  CharSourceRange Range,
+                                                 Optional<AccessKind> AccKind,
                                                  bool IsOpenBracket) {
   // Most of the clients treat subscript reference the same way as a
   // regular reference when called on the open bracket and
   // ignore the closing one.
   return IsOpenBracket ? visitDeclReference(D, Range, nullptr, nullptr, Type(),
-    ReferenceMetaData(SemaReferenceKind::SubscriptRef, None)) : true;
+    ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind)) : true;
 }
 
 bool SourceEntityWalker::visitCallArgName(Identifier Name,
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index 1848863..717e0c0 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -111,10 +111,11 @@
 }
 
 bool CursorInfoResolver::visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
-                                              bool IsOpenBracket) {
+                                                 Optional<AccessKind> AccKind,
+                                                 bool IsOpenBracket) {
   // We should treat both open and close brackets equally
   return visitDeclReference(D, Range, nullptr, nullptr, Type(),
-                    ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+                    ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
 }
 
 ResolvedCursorInfo CursorInfoResolver::resolve(SourceLoc Loc) {
@@ -698,6 +699,7 @@
   switch (Kind) {
   case RangeKind::SingleExpression: OS << "SingleExpression"; break;
   case RangeKind::SingleDecl: OS << "SingleDecl"; break;
+  case RangeKind::MultiTypeMemberDecl: OS << "MultiTypeMemberDecl"; break;
   case RangeKind::MultiStatement: OS << "MultiStatement"; break;
   case RangeKind::PartOfExpression: OS << "PartOfExpression"; break;
   case RangeKind::SingleStatement: OS << "SingleStatement"; break;
@@ -824,7 +826,7 @@
 
   return Nodes.end() != std::find_if(Nodes.begin(), Nodes.end(), [](ASTNode N) {
     ThrowingEntityAnalyzer Analyzer;
-    N.walk(Analyzer);
+    Analyzer.walk(N);
     return Analyzer.isThrowing();
   });
 }
@@ -883,6 +885,17 @@
       return llvm::any_of(StartMatches, IsCase) &&
           llvm::any_of(EndMatches, IsCase);
     }
+
+    bool isMultiTypeMemberDecl() {
+      if (StartMatches.empty() || EndMatches.empty())
+        return false;
+
+      // Multi-decls should have the same nominal type as a common parent
+      if (auto ParentDecl = Parent.dyn_cast<Decl *>())
+        return isa<NominalTypeDecl>(ParentDecl);
+
+      return false;
+    }
   };
 
 
@@ -911,6 +924,7 @@
     switch(Kind) {
     case RangeKind::Invalid:
     case RangeKind::SingleDecl:
+    case RangeKind::MultiTypeMemberDecl:
     case RangeKind::PartOfExpression:
       llvm_unreachable("cannot get type.");
 
@@ -1181,7 +1195,7 @@
   void postAnalysis(ASTNode EndNode) {
     // Visit the content of this node thoroughly, because the walker may
     // abort early.
-    EndNode.walk(CompleteWalker(this));
+    CompleteWalker(this).walk(EndNode);
 
     // Analyze whether declared decls in the range is referenced outside of it.
     FurtherReferenceWalker(this).walk(getImmediateContext());
@@ -1227,7 +1241,7 @@
     };
     for (auto N : Nodes) {
       ControlFlowStmtSelector TheWalker;
-      N.walk(TheWalker);
+      TheWalker.walk(N);
       for (auto Pair : TheWalker.Ranges) {
 
         // If the entire range does not include the target's range, we find
@@ -1247,7 +1261,15 @@
     Decl *D = Node.is<Decl*>() ? Node.get<Decl*>() : nullptr;
     analyzeDecl(D);
     auto &DCInfo = getCurrentDC();
-    switch (getRangeMatchKind(Node.getSourceRange())) {
+
+    auto NodeRange = Node.getSourceRange();
+
+    // Widen the node's source range to include all attributes to get a range
+    // match if a function with its attributes has been selected.
+    if (auto D = Node.dyn_cast<Decl *>())
+      NodeRange = D->getSourceRangeIncludingAttrs();
+
+    switch (getRangeMatchKind(NodeRange)) {
     case RangeMatchKind::NoneMatch: {
       // PatternBindingDecl is not visited; we need to explicitly analyze here.
       if (auto *VA = dyn_cast_or_null<VarDecl>(D))
@@ -1294,6 +1316,21 @@
                 llvm::makeArrayRef(DeclaredDecls),
                 llvm::makeArrayRef(ReferencedDecls)};
     }
+
+    if (DCInfo.isMultiTypeMemberDecl()) {
+      postAnalysis(DCInfo.EndMatches.back());
+      Result = {RangeKind::MultiTypeMemberDecl,
+                ReturnInfo(),
+                TokensInRange,
+                getImmediateContext(),
+                /*Common Parent Expr*/ nullptr,
+                /*SinleEntry*/ true,
+                hasUnhandledError(ContainedASTNodes),
+                getOrphanKind(ContainedASTNodes),
+                llvm::makeArrayRef(ContainedASTNodes),
+                llvm::makeArrayRef(DeclaredDecls),
+                llvm::makeArrayRef(ReferencedDecls)};
+    }
   }
 
   bool shouldEnter(ASTNode Node) {
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index 739b4f5..ec1f0d2 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -18,11 +18,13 @@
 #include "Fulfillment.h"
 #include "IRGenModule.h"
 
-#include "swift/AST/Decl.h"
-#include "swift/AST/SubstitutionMap.h"
-#include "swift/SIL/TypeLowering.h"
 #include "GenericRequirement.h"
 #include "ProtocolInfo.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/ProtocolConformance.h"
+#include "swift/AST/SubstitutionMap.h"
+#include "swift/SIL/SILWitnessTable.h"
+#include "swift/SIL/TypeLowering.h"
 
 using namespace swift;
 using namespace irgen;
@@ -145,18 +147,38 @@
   return false;
 }
 
-/// Given that we have a source for a witness table that the given type
-/// conforms to the given protocol, check to see if it fulfills anything.
+bool FulfillmentMap::searchConformance(
+    IRGenModule &IGM, const ProtocolConformance *conformance,
+    unsigned sourceIndex, MetadataPath &&path,
+    const InterestingKeysCallback &interestingKeys) {
+  bool hadFulfillment = false;
+
+  SILWitnessTable::enumerateWitnessTableConditionalConformances(
+      conformance, [&](unsigned index, CanType type, ProtocolDecl *protocol) {
+        MetadataPath conditionalPath = path;
+        conditionalPath.addConditionalConformanceComponent(index);
+        hadFulfillment |=
+            searchWitnessTable(IGM, type, protocol, sourceIndex,
+                               std::move(conditionalPath), interestingKeys);
+
+        return /*finished?*/ false;
+      });
+
+  return hadFulfillment;
+}
+
 bool FulfillmentMap::searchWitnessTable(IRGenModule &IGM,
                                         CanType type, ProtocolDecl *protocol,
                                         unsigned source, MetadataPath &&path,
                                         const InterestingKeysCallback &keys) {
+  assert(Lowering::TypeConverter::protocolRequiresWitnessTable(protocol));
+
   llvm::SmallPtrSet<ProtocolDecl*, 4> interestingConformancesBuffer;
-  llvm::SmallPtrSetImpl<ProtocolDecl*> *interestingConformances = nullptr;
+  llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances = nullptr;
 
   // If the interesting-keys set is limiting the set of interesting
   // conformances, collect that filter.
-  if (keys.isInterestingType(type) &&
+  if (keys.hasInterestingType(type) &&
       keys.hasLimitedInterestingConformances(type)) {
     // Bail out immediately if the set is empty.
     // This only makes sense because we're not trying to fulfill
@@ -173,13 +195,10 @@
                             interestingConformances);
 }
 
-bool FulfillmentMap::searchWitnessTable(IRGenModule &IGM,
-                                        CanType type, ProtocolDecl *protocol,
-                                        unsigned source, MetadataPath &&path,
-                                        const InterestingKeysCallback &keys,
-                                  const llvm::SmallPtrSetImpl<ProtocolDecl*> *
-                                          interestingConformances) {
-  assert(Lowering::TypeConverter::protocolRequiresWitnessTable(protocol));
+bool FulfillmentMap::searchWitnessTable(
+    IRGenModule &IGM, CanType type, ProtocolDecl *protocol, unsigned source,
+    MetadataPath &&path, const InterestingKeysCallback &keys,
+    llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances) {
 
   bool hadFulfillment = false;
 
@@ -252,24 +271,8 @@
     MetadataPath argPath = path;
     argPath.addNominalTypeArgumentConformanceComponent(reqtIndex);
 
-    llvm::SmallPtrSet<ProtocolDecl*, 4> interestingConformancesBuffer;
-    llvm::SmallPtrSetImpl<ProtocolDecl*> *interestingConformances = nullptr;
-
-    // If the interesting-keys set is limiting the set of interesting
-    // conformances, collect that filter.
-    if (keys.hasLimitedInterestingConformances(arg)) {
-      // Bail out immediately if the set is empty.
-      auto requiredConformances = keys.getInterestingConformances(arg);
-      if (requiredConformances.empty()) return;
-
-      interestingConformancesBuffer.insert(requiredConformances.begin(),
-                                           requiredConformances.end());
-      interestingConformances = &interestingConformancesBuffer;
-    }
-
-    hadFulfillment |=
-      searchWitnessTable(IGM, arg, conf->getRequirement(), source,
-                         std::move(argPath), keys, interestingConformances);
+    hadFulfillment |= searchWitnessTable(IGM, arg, conf->getRequirement(),
+                                         source, std::move(argPath), keys);
   });
 
   return hadFulfillment;
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 65737b6..73525d3 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -93,6 +93,11 @@
                           unsigned sourceIndex, MetadataPath &&path,
                           const InterestingKeysCallback &interestingKeys);
 
+  bool searchConformance(IRGenModule &IGM,
+                         const ProtocolConformance *conformance,
+                         unsigned sourceIndex, MetadataPath &&path,
+                         const InterestingKeysCallback &interestingKeys);
+
   /// Search the given witness table for useful fulfillments.
   ///
   /// \return true if any fulfillments were added by this search.
@@ -140,12 +145,10 @@
   /// Search the given witness table for useful fulfillments.
   ///
   /// \return true if any fulfillments were added by this search.
-  bool searchWitnessTable(IRGenModule &IGM, CanType type, ProtocolDecl *protocol,
-                          unsigned sourceIndex, MetadataPath &&path,
-                          const InterestingKeysCallback &interestingKeys,
-                          const llvm::SmallPtrSetImpl<ProtocolDecl*> *
-                            interestingConformances);
-
+  bool searchWitnessTable(
+      IRGenModule &IGM, CanType type, ProtocolDecl *protocol, unsigned source,
+      MetadataPath &&path, const InterestingKeysCallback &keys,
+      llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances);
 };
 
 }
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 5e5e9b2..0ddde22 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -73,7 +73,7 @@
 bool IRGenerator::tryEnableLazyTypeMetadata(NominalTypeDecl *Nominal) {
   // When compiling with -Onone keep all metadata for the debugger. Even if it
   // is not used by the program itself.
-  if (!Opts.Optimize)
+  if (!Opts.shouldOptimize())
     return false;
 
   switch (Nominal->getKind()) {
@@ -1329,7 +1329,7 @@
                   llvm::GlobalValue::VisibilityTypes,
                   llvm::GlobalValue::DLLStorageClassTypes>
 getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
-             bool isSILOnly, ForDefinition_t isDefinition,
+             ForDefinition_t isDefinition,
              bool isWeakImported) {
 #define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE)                               \
   std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage,                         \
@@ -1352,19 +1352,6 @@
 
   switch (linkage) {
   case SILLinkage::Public:
-    // Don't code-gen transparent functions. Internal linkage will enable llvm
-    // to delete transparent functions except they are referenced from somewhere
-    // (i.e. the function pointer is taken).
-    //
-    // In case we are generating multiple LLVM modules, we still have to use
-    // ExternalLinkage so that modules can cross-reference transparent
-    // functions.
-    //
-    // TODO: In non-whole-module-opt the generated swiftmodules are "linked" and
-    // this strips all serialized transparent functions. So we have to code-gen
-    // transparent functions in non-whole-module-opt.
-    if (isSILOnly && !info.HasMultipleIGMs && info.IsWholeModule)
-      return RESULT(Internal, Default, Default);
     return std::make_tuple(llvm::GlobalValue::ExternalLinkage,
                            PublicDefinitionVisibility, ExportedStorage);
 
@@ -1389,9 +1376,6 @@
 
   case SILLinkage::PublicExternal: {
     if (isDefinition) {
-      // Transparent function are not available externally.
-      if (isSILOnly)
-        return RESULT(LinkOnceODR, Hidden, Default);
       return std::make_tuple(llvm::GlobalValue::AvailableExternallyLinkage,
                              llvm::GlobalValue::DefaultVisibility,
                              ExportedStorage);
@@ -1426,7 +1410,6 @@
   UniversalLinkageInfo linkInfo(IGM);
   auto linkage =
       getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
-                   entity.isSILOnly(),
                    ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
   global->setLinkage(std::get<0>(linkage));
   global->setVisibility(std::get<1>(linkage));
@@ -1458,7 +1441,6 @@
 
   std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
       getIRLinkage(linkInfo, entity.getLinkage(isDefinition),
-                   entity.isSILOnly(),
                    isDefinition, entity.isWeakImported(swiftModule));
 
   result.ForDefinition = isDefinition;
@@ -1469,14 +1451,13 @@
 LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
                        StringRef name,
                        SILLinkage linkage,
-                       bool isSILOnly,
                        ForDefinition_t isDefinition,
                        bool isWeakImported) {
   LinkInfo result;
 
   result.Name += name;
   std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
-    getIRLinkage(linkInfo, linkage, isSILOnly,
+    getIRLinkage(linkInfo, linkage,
                  isDefinition, isWeakImported);
   result.ForDefinition = isDefinition;
   return result;
@@ -1490,7 +1471,8 @@
 llvm::Function *irgen::createFunction(IRGenModule &IGM,
                                       LinkInfo &linkInfo,
                                       const Signature &signature,
-                                      llvm::Function *insertBefore) {
+                                      llvm::Function *insertBefore,
+                                      OptimizationMode FuncOptMode) {
   auto name = linkInfo.getName();
 
   llvm::Function *existing = IGM.Module.getFunction(name);
@@ -1519,7 +1501,7 @@
  }
 
   llvm::AttrBuilder initialAttrs;
-  IGM.constructInitialFnAttributes(initialAttrs);
+  IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode);
   // Merge initialAttrs with attrs.
   auto updatedAttrs =
     signature.getAttributes().addAttributes(IGM.getLLVMContext(),
@@ -1901,7 +1883,8 @@
                                llvm::AttributeList::FunctionIndex,
                                llvm::Attribute::ReadOnly);
   }
-  fn = createFunction(*this, link, signature, insertBefore);
+  fn = createFunction(*this, link, signature, insertBefore,
+                      f->getOptimizationMode());
 
   // If we have an order number for this function, set it up as appropriate.
   if (hasOrderNumber) {
@@ -3138,11 +3121,10 @@
   metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
 
   // Get a reference count of two.
-  auto *strongRefCountInit = llvm::ConstantInt::get(
-      Int32Ty,
-      InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+  auto *refCountInit = llvm::ConstantInt::get(
+      IntPtrTy,
+      InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
           .getBitsValue());
-  auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
 
   auto *count = llvm::ConstantInt::get(Int32Ty, utf8.size());
   // Capacity is length plus one because of the implicitly added '\0'
@@ -3150,9 +3132,8 @@
   auto *capacity = llvm::ConstantInt::get(Int32Ty, utf8.size() + 1);
   auto *flags = llvm::ConstantInt::get(Int8Ty, 0);
 
-  // FIXME: Big endian-ness.
   llvm::Constant *heapObjectHeaderFields[] = {
-      metaclass, strongRefCountInit, unownedRefCountInit
+      metaclass, refCountInit
   };
 
   auto *initRefCountStruct = llvm::ConstantStruct::get(
@@ -3216,11 +3197,10 @@
   metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
 
   // Get a reference count of two.
-  auto *strongRefCountInit = llvm::ConstantInt::get(
-      Int32Ty,
-      InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+  auto *refCountInit = llvm::ConstantInt::get(
+      IntPtrTy,
+      InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
           .getBitsValue());
-  auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
 
   auto *count = llvm::ConstantInt::get(Int32Ty, utf16Length);
   auto *capacity = llvm::ConstantInt::get(Int32Ty, utf16Length + 1);
@@ -3228,7 +3208,7 @@
   auto *padding = llvm::ConstantInt::get(Int8Ty, 0);
 
   llvm::Constant *heapObjectHeaderFields[] = {
-      metaclass, strongRefCountInit, unownedRefCountInit
+      metaclass, refCountInit
   };
 
   auto *initRefCountStruct = llvm::ConstantStruct::get(
@@ -3312,11 +3292,9 @@
     return entry;
   }
 
-  auto fnType = llvm::FunctionType::get(VoidTy,
-                                        { WitnessTablePtrTy,
-                                          TypeMetadataPtrTy,
-                                          Int8PtrPtrTy },
-                                        /*varargs*/ false);
+  auto fnType = llvm::FunctionType::get(
+      VoidTy, {WitnessTablePtrTy, TypeMetadataPtrTy, Int8PtrPtrTy},
+      /*varargs*/ false);
   Signature signature(fnType, llvm::AttributeList(), DefaultCC);
   LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
   entry = createFunction(*this, link, signature);
@@ -3359,9 +3337,12 @@
   }
 
   llvm::FunctionType *fnType;
-  if (conf->getDeclContext()->isGenericContext()) {
-    fnType = llvm::FunctionType::get(WitnessTablePtrTy, {TypeMetadataPtrTy},
-                                     false);
+  if (conf->witnessTableAccessorRequiresArguments()) {
+    // conditional requirements are passed indirectly, as an array of witness
+    // tables.
+    fnType = llvm::FunctionType::get(
+        WitnessTablePtrTy, {TypeMetadataPtrTy, WitnessTablePtrPtrTy, SizeTy},
+        false);
   } else {
     fnType = llvm::FunctionType::get(WitnessTablePtrTy, false);
   }
diff --git a/lib/IRGen/GenDecl.h b/lib/IRGen/GenDecl.h
index fd233bd..c394d76 100644
--- a/lib/IRGen/GenDecl.h
+++ b/lib/IRGen/GenDecl.h
@@ -17,6 +17,7 @@
 #ifndef SWIFT_IRGEN_GENDECL_H
 #define SWIFT_IRGEN_GENDECL_H
 
+#include "swift/Basic/OptimizationMode.h"
 #include "llvm/IR/CallingConv.h"
 #include "DebugTypeInfo.h"
 #include "IRGen.h"
@@ -35,8 +36,9 @@
   llvm::Function *createFunction(IRGenModule &IGM,
                                  LinkInfo &linkInfo,
                                  const Signature &signature,
-                                 llvm::Function *insertBefore = nullptr);
-
+                                 llvm::Function *insertBefore = nullptr,
+                                 OptimizationMode FuncOptMode =
+                                   OptimizationMode::NotSet);
 
   llvm::GlobalVariable *createVariable(IRGenModule &IGM,
                                        LinkInfo &linkInfo,
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 9e7b6ed..4a0cabf 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -2128,7 +2128,7 @@
 
         //  Size = ((sizeof(HeapObject) + align) & ~align) + size
         auto *heapHeaderSize = llvm::ConstantInt::get(
-            IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+            IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
         size = Builder.CreateAdd(
             Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
                               Builder.CreateNot(alignmentMask)),
@@ -2222,7 +2222,7 @@
 
           //  StartOffset = ((sizeof(HeapObject) + align) & ~align)
           auto *heapHeaderSize = llvm::ConstantInt::get(
-              IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+              IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
           auto *startOffset = Builder.CreateAnd(
               Builder.CreateAdd(heapHeaderSize, alignmentMask),
               Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp
index 0cfc7e8..31d2549 100644
--- a/lib/IRGen/GenHeap.cpp
+++ b/lib/IRGen/GenHeap.cpp
@@ -1294,7 +1294,7 @@
 /// optimizer not to touch this value.
 void IRGenFunction::emitFixLifetime(llvm::Value *value) {
   // If we aren't running the LLVM ARC optimizer, we don't need to emit this.
-  if (!IGM.IRGen.Opts.Optimize || IGM.IRGen.Opts.DisableLLVMARCOpts)
+  if (!IGM.IRGen.Opts.shouldOptimize() || IGM.IRGen.Opts.DisableLLVMARCOpts)
     return;
   if (doesNotRequireRefCounting(value)) return;
   emitUnaryRefCountCall(*this, IGM.getFixLifetimeFn(), value);
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index 198f9cc..c2babaa 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -330,7 +330,6 @@
     
     auto linkInfo = LinkInfo::get(IGM, "swift_keyPathGenericWitnessTable",
                                   SILLinkage::PublicExternal,
-                                  /*sil only*/ false,
                                   NotForDefinition,
                                   /*weak imported*/ false);
     
@@ -700,11 +699,6 @@
   fields.add(emitMetadataGenerator(rootTy));
   fields.add(emitMetadataGenerator(valueTy));
   
-  // TODO: 32-bit heap object header still has an extra word
-  if (SizeTy == Int32Ty) {
-    fields.addInt32(0);
-  }
-  
 #ifndef NDEBUG
   auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
   unsigned expectedObjectHeaderSize;
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index bdef251..ef8f1c8 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -108,6 +108,7 @@
 
 llvm::Value *irgen::emitObjCMetadataRefForMetadata(IRGenFunction &IGF,
                                                    llvm::Value *classPtr) {
+  assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
   classPtr = IGF.Builder.CreateBitCast(classPtr, IGF.IGM.ObjCClassPtrTy);
   
   // Fetch the metadata for that class.
@@ -704,43 +705,32 @@
                         "metadata ref for generic function type");
       return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
     }
-      
-    llvm::Value *extractAndMarkResultType(CanFunctionType type) {
-      // If the function type throws, set the lower bit of the return type
-      // address, so that we can carry this information over to the function
-      // type metadata.
-      auto metadata = IGF.emitTypeMetadataRef(type->getResult()->
-                                              getCanonicalType());
-      return metadata;
-    }
 
-    llvm::Value *extractAndMarkInOut(AnyFunctionType::CanParam param) {
-      // If the type is inout, get the metadata for its inner object type
-      // instead, and then set the lowest bit to help the runtime unique
-      // the metadata type for this function.
+    llvm::Value *getFunctionParameterRef(AnyFunctionType::CanParam param) {
       auto type = param.getType();
-      if (param.getParameterFlags().isInOut()) {
-        auto objectType = type->getInOutObjectType()->getCanonicalType();
-        auto metadata = IGF.emitTypeMetadataRef(objectType);
-        auto metadataInt = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy);
-        auto inoutFlag = llvm::ConstantInt::get(IGF.IGM.SizeTy, 1);
-        auto marked = IGF.Builder.CreateOr(metadataInt, inoutFlag);
-        return IGF.Builder.CreateIntToPtr(marked, IGF.IGM.Int8PtrTy);
-      }
-      
-      auto metadata = IGF.emitTypeMetadataRef(type);
-      return IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrTy);
+      if (param.getParameterFlags().isInOut())
+        type = type->getInOutObjectType()->getCanonicalType();
+      return IGF.emitTypeMetadataRef(type);
     }
 
     llvm::Value *visitFunctionType(CanFunctionType type) {
       if (auto metatype = tryGetLocal(type))
         return metatype;
 
-      auto resultMetadata = extractAndMarkResultType(type);
+      auto result =
+          IGF.emitTypeMetadataRef(type->getResult()->getCanonicalType());
 
       auto params = type.getParams();
       auto numParams = params.size();
 
+      bool hasFlags = false;
+      for (auto param : params) {
+        if (!param.getParameterFlags().isNone()) {
+          hasFlags = true;
+          break;
+        }
+      }
+
       // Map the convention to a runtime metadata value.
       FunctionMetadataConvention metadataConvention;
       switch (type->getRepresentation()) {
@@ -759,78 +749,136 @@
       }
 
       auto flagsVal = FunctionTypeFlags()
-                          .withNumArguments(numParams)
+                          .withNumParameters(numParams)
                           .withConvention(metadataConvention)
-                          .withThrows(type->throws());
+                          .withThrows(type->throws())
+                          .withParameterFlags(hasFlags);
 
       auto flags = llvm::ConstantInt::get(IGF.IGM.SizeTy,
                                           flagsVal.getIntValue());
 
-      switch (numParams) {
-      case 1: {
-        auto arg0 = extractAndMarkInOut(params[0]);
-        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadata1Fn(),
-                                           {flags, arg0, resultMetadata});
-        call->setDoesNotThrow();
-        return setLocal(CanType(type), call);
-        }
+      auto collectParameters =
+          [&](llvm::function_ref<void(unsigned, llvm::Value *,
+                                      ParameterFlags flags)>
+                  processor) {
+            for (auto index : indices(params)) {
+              auto param = params[index];
+              auto flags = param.getParameterFlags();
 
-        case 2: {
-          auto arg0 = extractAndMarkInOut(params[0]);
-          auto arg1 = extractAndMarkInOut(params[1]);
-          auto call = IGF.Builder.CreateCall(
-                                            IGF.IGM.getGetFunctionMetadata2Fn(),
-                                            {flags, arg0, arg1, resultMetadata});
-          call->setDoesNotThrow();
-          return setLocal(CanType(type), call);
-        }
+              auto parameterFlags = ParameterFlags()
+                                        .withInOut(flags.isInOut())
+                                        .withShared(flags.isShared())
+                                        .withVariadic(flags.isVariadic());
 
-        case 3: {
-          auto arg0 = extractAndMarkInOut(params[0]);
-          auto arg1 = extractAndMarkInOut(params[1]);
-          auto arg2 = extractAndMarkInOut(params[2]);
-          auto call = IGF.Builder.CreateCall(
-                                            IGF.IGM.getGetFunctionMetadata3Fn(),
-                                            {flags, arg0, arg1, arg2,
-                                             resultMetadata});
-          call->setDoesNotThrow();
-          return setLocal(CanType(type), call);
-        }
+              processor(index, getFunctionParameterRef(param), parameterFlags);
+            }
+          };
+
+      auto constructSimpleCall =
+          [&](llvm::SmallVectorImpl<llvm::Value *> &arguments)
+          -> llvm::Constant * {
+        arguments.push_back(flags);
+
+        collectParameters([&](unsigned i, llvm::Value *typeRef,
+                              ParameterFlags flags) {
+          arguments.push_back(typeRef);
+          if (hasFlags)
+            arguments.push_back(
+                llvm::ConstantInt::get(IGF.IGM.Int32Ty, flags.getIntValue()));
+        });
+
+        arguments.push_back(result);
+
+        switch (params.size()) {
+        case 1:
+          return hasFlags ? IGF.IGM.getGetFunctionMetadata1WithFlagsFn()
+                          : IGF.IGM.getGetFunctionMetadata1Fn();
+
+        case 2:
+          return hasFlags ? IGF.IGM.getGetFunctionMetadata2WithFlagsFn()
+                          : IGF.IGM.getGetFunctionMetadata2Fn();
+
+        case 3:
+          return hasFlags ? IGF.IGM.getGetFunctionMetadata3WithFlagsFn()
+                          : IGF.IGM.getGetFunctionMetadata3Fn();
 
         default:
-          auto arrayTy = llvm::ArrayType::get(IGF.IGM.Int8PtrTy, numParams + 2);
-          Address buffer = IGF.createAlloca(arrayTy,
-                                            IGF.IGM.getPointerAlignment(),
-                                            "function-arguments");
-          IGF.Builder.CreateLifetimeStart(buffer,
+          llvm_unreachable("supports only 1/2/3 parameter functions");
+        }
+      };
+
+      auto getArrayFor = [&](llvm::Type *elementType, unsigned size,
+                             const llvm::Twine &name) -> Address {
+        auto arrayTy = llvm::ArrayType::get(elementType, size);
+        return IGF.createAlloca(arrayTy, IGF.IGM.getPointerAlignment(), name);
+      };
+
+      switch (numParams) {
+      case 1:
+      case 2:
+      case 3: {
+        llvm::SmallVector<llvm::Value *, 8> arguments;
+        auto *metadataFn = constructSimpleCall(arguments);
+        auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
+        call->setDoesNotThrow();
+        return setLocal(CanType(type), call);
+      }
+
+      default:
+        auto *const Int32Ptr = IGF.IGM.Int32Ty->getPointerTo();
+
+        llvm::SmallVector<llvm::Value *, 8> arguments;
+        arguments.push_back(flags);
+
+        Address parameters;
+        if (!params.empty()) {
+          parameters = getArrayFor(IGF.IGM.TypeMetadataPtrTy, numParams,
+                                   "function-parameters");
+
+          IGF.Builder.CreateLifetimeStart(parameters,
                                           IGF.IGM.getPointerSize() * numParams);
-          Address pointerToFirstArg = IGF.Builder.CreateStructGEP(buffer, 0,
-                                                                   Size(0));
-          Address flagsPtr = IGF.Builder.CreateBitCast(pointerToFirstArg,
-                                               IGF.IGM.SizeTy->getPointerTo());
-          IGF.Builder.CreateStore(flags, flagsPtr);
 
-          for (auto i : indices(params)) {
-            auto argMetadata = extractAndMarkInOut(params[i]);
-            Address argPtr = IGF.Builder.CreateStructGEP(buffer, i + 1,
+          ConstantInitBuilder paramFlags(IGF.IGM);
+          auto flagsArr = paramFlags.beginArray();
+          collectParameters([&](unsigned i, llvm::Value *typeRef,
+                                ParameterFlags flags) {
+            auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
                                                       IGF.IGM.getPointerSize());
-            IGF.Builder.CreateStore(argMetadata, argPtr);
+            IGF.Builder.CreateStore(typeRef, argPtr);
+            if (hasFlags)
+              flagsArr.addInt32(flags.getIntValue());
+          });
+
+          auto parametersPtr =
+              IGF.Builder.CreateStructGEP(parameters, 0, Size(0));
+          arguments.push_back(parametersPtr.getAddress());
+
+          if (hasFlags) {
+            auto *flagsVar = flagsArr.finishAndCreateGlobal(
+                "parameter-flags", IGF.IGM.getPointerAlignment(),
+                /* constant */ true);
+            arguments.push_back(IGF.Builder.CreateBitCast(flagsVar, Int32Ptr));
+          } else {
+            flagsArr.abandon();
+            arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
           }
+        } else {
+          arguments.push_back(llvm::ConstantPointerNull::get(
+              IGF.IGM.TypeMetadataPtrTy->getPointerTo()));
+          arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
+        }
 
-          Address resultPtr = IGF.Builder.CreateStructGEP(
-              buffer, numParams + 1, IGF.IGM.getPointerSize());
-          resultPtr = IGF.Builder.CreateBitCast(resultPtr,
-                                     IGF.IGM.TypeMetadataPtrTy->getPointerTo());
-          IGF.Builder.CreateStore(resultMetadata, resultPtr);
+        arguments.push_back(result);
 
-          auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
-                                             pointerToFirstArg.getAddress());
-          call->setDoesNotThrow();
+        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
+                                           arguments);
+        call->setDoesNotThrow();
 
-          IGF.Builder.CreateLifetimeEnd(buffer,
+        if (parameters.isValid())
+          IGF.Builder.CreateLifetimeEnd(parameters,
                                         IGF.IGM.getPointerSize() * numParams);
 
-          return setLocal(type, call);
+        return setLocal(type, call);
       }
     }
 
@@ -933,6 +981,9 @@
       llvm_unreachable("should not be asking for metadata of a lowered SIL "
                        "function type--SILGen should have used the AST type");
     }
+    llvm::Value *visitSILTokenType(CanSILTokenType type) {
+      llvm_unreachable("should not be asking for metadata of a SILToken type");
+    }
 
     llvm::Value *visitArchetypeType(CanArchetypeType type) {
       return emitArchetypeTypeMetadataRef(IGF, type);
@@ -1337,7 +1388,7 @@
     cacheVariable = cast<llvm::GlobalVariable>(
         IGM.getAddrOfTypeMetadataLazyCacheVariable(type, ForDefinition));
 
-    if (IGM.getOptions().OptimizeForSize)
+    if (IGM.getOptions().optimizeForSize())
       accessor->addFnAttr(llvm::Attribute::NoInline);
   }
 
@@ -1381,7 +1432,7 @@
   if (!shouldDefine || !accessor->empty())
     return accessor;
 
-  if (IGM.getOptions().OptimizeForSize)
+  if (IGM.getOptions().optimizeForSize())
     accessor->addFnAttr(llvm::Attribute::NoInline);
 
   emitLazyCacheAccessFunction(IGM, accessor, /*cacheVariable=*/nullptr,
@@ -4204,46 +4255,16 @@
   if (hasKnownSwiftMetadata(IGF.IGM, type))
     return metatype;
 
-  // Otherwise, we inline a little operation here.
-
-  // Load the metatype kind.
-  auto metatypeKindAddr =
-    Address(IGF.Builder.CreateStructGEP(/*Ty=*/nullptr, metatype, 0),
-            IGF.IGM.getPointerAlignment());
-  auto metatypeKind =
-    IGF.Builder.CreateLoad(metatypeKindAddr, metatype->getName() + ".kind");
-
-  // Compare it with the class wrapper kind.
-  auto classWrapperKind =
-    llvm::ConstantInt::get(IGF.IGM.MetadataKindTy,
-                           unsigned(MetadataKind::ObjCClassWrapper));
-  auto isObjCClassWrapper =
-    IGF.Builder.CreateICmpEQ(metatypeKind, classWrapperKind,
-                             "isObjCClassWrapper");
-
-  // Branch based on that.
-  llvm::BasicBlock *contBB = IGF.createBasicBlock("metadataForClass.cont");
-  llvm::BasicBlock *wrapBB = IGF.createBasicBlock("isWrapper");
-  IGF.Builder.CreateCondBr(isObjCClassWrapper, wrapBB, contBB);
-  llvm::BasicBlock *origBB = IGF.Builder.GetInsertBlock();
-
-  // If it's a wrapper, load from the 'Class' field, which is at index 1.
-  // TODO: if we guaranteed that this load couldn't crash, we could use
-  // a select here instead, which might be profitable.
-  IGF.Builder.emitBlock(wrapBB);
-  auto classFromWrapper = 
-    emitInvariantLoadFromMetadataAtIndex(IGF, metatype, 1,
-                                         IGF.IGM.TypeMetadataPtrTy);
-  IGF.Builder.CreateBr(contBB);
-
-  // Continuation block.
-  IGF.Builder.emitBlock(contBB);
-  auto phi = IGF.Builder.CreatePHI(IGF.IGM.TypeMetadataPtrTy, 2,
-                                   metatype->getName() + ".class");
-  phi->addIncoming(metatype, origBB);
-  phi->addIncoming(classFromWrapper, wrapBB);
-
-  return phi;
+  // Otherwise, we may have to unwrap an ObjC class wrapper.
+  assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
+  metatype = IGF.Builder.CreateBitCast(metatype, IGF.IGM.TypeMetadataPtrTy);
+  
+  // Fetch the metadata for that class.
+  auto call = IGF.Builder.CreateCall(IGF.IGM.getGetObjCClassFromMetadataFn(),
+                                     metatype);
+  call->setDoesNotThrow();
+  call->setDoesNotAccessMemory();
+  return call;
 }
 
 /// Load the correct virtual function for the given class method.
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index 2a6c1c5..10d28c2 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -143,7 +143,7 @@
   // If we're emitting optimized code, record the string in the module
   // and let the late ARC pass insert it, but don't generate any calls
   // right now.
-  if (IRGen.Opts.Optimize) {
+  if (IRGen.Opts.shouldOptimize()) {
     llvm::NamedMDNode *metadata =
       Module.getOrInsertNamedMetadata(
                             "clang.arc.retainAutoreleasedReturnValueMarker");
@@ -908,7 +908,8 @@
       subIGF.emitObjCAutoreleaseCall(self);
     }
     // Release the context.
-    subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
+    if (!resultType->isCalleeGuaranteed())
+      subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
   };
   
    // Emit the call and produce the return value.
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index e784a90..3338f58 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -735,7 +735,7 @@
                                                     SILType T,
                                                     llvm::Value *numEmptyCases,
                                                     Address destObject) {
-  if (!IGF.IGM.getOptions().OptimizeForSize) {
+  if (!IGF.optimizeForSize()) {
     llvm::Value *metadata;
     auto fn = IGF.emitValueWitnessFunctionRef(
         T, metadata, ValueWitness::GetEnumTagSinglePayload);
@@ -755,7 +755,7 @@
 llvm::Value *irgen::emitStoreEnumTagSinglePayloadCall(
     IRGenFunction &IGF, SILType T, llvm::Value *whichCase,
     llvm::Value *numEmptyCases, Address destObject) {
-  if (!IGF.IGM.getOptions().OptimizeForSize) {
+  if (!IGF.optimizeForSize()) {
     llvm::Value *metadata;
     auto fn = IGF.emitValueWitnessFunctionRef(
         T, metadata, ValueWitness::StoreEnumTagSinglePayload);
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 4797745..d9bb28c 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -74,6 +74,10 @@
 using namespace swift;
 using namespace irgen;
 
+// Return the offset one should do on a witness table pointer to retrieve the
+// `index`th piece of private data.
+static int privateIndexToTableOffset(unsigned index) { return -1 - (int)index; }
+
 namespace {
 
 /// A class for computing how to pass arguments to a polymorphic
@@ -138,9 +142,32 @@
                          bool isSelfParameter);
 
   void addSelfMetadataFulfillment(CanType arg);
-  void addSelfWitnessTableFulfillment(CanType arg, ProtocolDecl *proto);
+  void addSelfWitnessTableFulfillment(CanType arg,
+                                      ProtocolConformanceRef conformance);
 
   void addPseudogenericFulfillments();
+
+  struct FulfillmentMapCallback : FulfillmentMap::InterestingKeysCallback {
+    PolymorphicConvention &Self;
+    FulfillmentMapCallback(PolymorphicConvention &self) : Self(self) {}
+
+    bool isInterestingType(CanType type) const override {
+      return type->isTypeParameter();
+    }
+    bool hasInterestingType(CanType type) const override {
+      return type->hasTypeParameter();
+    }
+    bool hasLimitedInterestingConformances(CanType type) const override {
+      return true;
+    }
+    GenericSignature::ConformsToArray
+    getInterestingConformances(CanType type) const override {
+      return Self.getConformsTo(type);
+    }
+    CanType getSuperclassBound(CanType type) const override {
+      return Self.getSuperclassBound(type);
+    }
+  };
 };
 
 } // end anonymous namespace
@@ -163,9 +190,9 @@
   }
 
   if (rep == SILFunctionTypeRepresentation::WitnessMethod) {
-    // Protocol witnesses always derive all polymorphic parameter
-    // information from the Self argument. We also *cannot* consider other
-    // arguments; doing so would potentially make the signature
+    // Protocol witnesses always derive all polymorphic parameter information
+    // from the Self and Self witness table arguments. We also *cannot* consider
+    // other arguments; doing so would potentially make the signature
     // incompatible with other witnesses for the same method.
     considerWitnessSelf(fnType);
   } else if (rep == SILFunctionTypeRepresentation::ObjCMethod) {
@@ -280,27 +307,7 @@
 bool PolymorphicConvention::considerType(CanType type, IsExact_t isExact,
                                          unsigned sourceIndex,
                                          MetadataPath &&path) {
-  struct Callback : FulfillmentMap::InterestingKeysCallback {
-    PolymorphicConvention &Self;
-    Callback(PolymorphicConvention &self) : Self(self) {}
-
-    bool isInterestingType(CanType type) const override {
-      return type->isTypeParameter();
-    }
-    bool hasInterestingType(CanType type) const override {
-      return type->hasTypeParameter();
-    }
-    bool hasLimitedInterestingConformances(CanType type) const override {
-      return true;
-    }
-    GenericSignature::ConformsToArray
-    getInterestingConformances(CanType type) const override {
-      return Self.getConformsTo(type);
-    }
-    CanType getSuperclassBound(CanType type) const override {
-      return Self.getSuperclassBound(type);
-    }
-  } callbacks(*this);
+  FulfillmentMapCallback callbacks(*this);
   return Fulfillments.searchTypeMetadata(IGM, type, isExact, sourceIndex,
                                          std::move(path), callbacks);
 }
@@ -308,29 +315,17 @@
 void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
   CanType selfTy = fnType->getSelfInstanceType();
   auto conformance = fnType->getWitnessMethodConformance();
-  auto protocol = conformance.getRequirement();
 
   // First, bind type metadata for Self.
   Sources.emplace_back(MetadataSource::Kind::SelfMetadata,
                        MetadataSource::InvalidSourceIndex,
                        selfTy);
 
-  if (auto *proto = fnType->getDefaultWitnessMethodProtocol()) {
+  if (fnType->getDefaultWitnessMethodProtocol() ||
+      fnType->getWitnessMethodClass(M)) {
     // The Self type is abstract, so we can fulfill its metadata from
     // the Self metadata parameter.
     addSelfMetadataFulfillment(selfTy);
-
-    // The witness table for the Self : P conformance can be
-    // fulfilled from the Self witness table parameter.
-    Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
-                         MetadataSource::InvalidSourceIndex,
-                         selfTy);
-    addSelfWitnessTableFulfillment(selfTy, proto);
-  } else if (auto *classDecl = fnType->getWitnessMethodClass(M)) {
-    // The Self type is abstract, so we can fulfill its metadata from
-    // the Self metadata parameter.
-    addSelfMetadataFulfillment(selfTy);
-    addSelfWitnessTableFulfillment(selfTy, protocol);
   } else {
     // If the Self type is concrete, we have a witness thunk with a
     // fully substituted Self type. The witness table parameter is not
@@ -342,9 +337,13 @@
     //
     // For now, just fulfill the generic arguments of 'Self'.
     considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
-
-    addSelfWitnessTableFulfillment(selfTy, protocol);
   }
+
+  // The witness table for the Self : P conformance can be
+  // fulfilled from the Self witness table parameter.
+  Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
+                       MetadataSource::InvalidSourceIndex, selfTy);
+  addSelfWitnessTableFulfillment(selfTy, conformance);
 }
 
 void PolymorphicConvention::considerObjCGenericSelf(CanSILFunctionType fnType) {
@@ -429,9 +428,17 @@
   Fulfillments.addFulfillment({arg, nullptr}, source, MetadataPath());
 }
 
-void PolymorphicConvention::addSelfWitnessTableFulfillment(CanType arg, ProtocolDecl *proto) {
+void PolymorphicConvention::addSelfWitnessTableFulfillment(
+    CanType arg, ProtocolConformanceRef conformance) {
+  auto proto = conformance.getRequirement();
   unsigned source = Sources.size() - 1;
   Fulfillments.addFulfillment({arg, proto}, source, MetadataPath());
+
+  if (conformance.isConcrete()) {
+    FulfillmentMapCallback callbacks(*this);
+    Fulfillments.searchConformance(IGM, conformance.getConcrete(), source,
+                                   MetadataPath(), callbacks);
+  }
 }
 
 const Fulfillment *
@@ -549,20 +556,48 @@
 
     case MetadataSource::Kind::SelfWitnessTable: {
       assert(witnessMetadata && "no metadata for witness method");
-      llvm::Value *wtable = witnessMetadata->SelfWitnessTable;
-      assert(wtable && "no Self witness table for witness method");
+      llvm::Value *selfTable = witnessMetadata->SelfWitnessTable;
+      assert(selfTable && "no Self witness table for witness method");
 
       // Mark this as the cached witness table for Self.
+      auto conformance = FnType->getWitnessMethodConformance();
+      auto selfProto = conformance.getRequirement();
 
-      if (auto *proto = FnType->getDefaultWitnessMethodProtocol()) {
-        auto selfTy = FnType->getSelfInstanceType();
-        CanType argTy = getTypeInContext(selfTy);
-        auto archetype = cast<ArchetypeType>(argTy);
+      auto selfTy = FnType->getSelfInstanceType();
+      CanType argTy = getTypeInContext(selfTy);
+      if (auto archetype = dyn_cast<ArchetypeType>(argTy)) {
+        setProtocolWitnessTableName(IGF.IGM, selfTable, argTy, selfProto);
+        IGF.setUnscopedLocalTypeData(
+            archetype,
+            LocalTypeDataKind::forAbstractProtocolWitnessTable(selfProto),
+            selfTable);
+      }
 
-        setProtocolWitnessTableName(IGF.IGM, wtable, argTy, proto);
-        IGF.setUnscopedLocalTypeData(archetype,
-                                     LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
-                                     wtable);
+      if (conformance.isConcrete()) {
+        // Now bind all the conditional witness tables that can be pulled out of
+        // the self witness table.
+        SILWitnessTable::enumerateWitnessTableConditionalConformances(
+            conformance.getConcrete(),
+            [&](unsigned index, CanType type, ProtocolDecl *proto) {
+              auto archetype = getTypeInContext(type);
+              if (isa<ArchetypeType>(archetype)) {
+                WitnessIndex wIndex(privateIndexToTableOffset(index),
+                                    /*prefix*/ false);
+
+                auto table =
+                    emitInvariantLoadOfOpaqueWitness(IGF, selfTable, wIndex);
+                table =
+                    IGF.Builder.CreateBitCast(table, IGF.IGM.WitnessTablePtrTy);
+                setProtocolWitnessTableName(IGF.IGM, table, archetype, proto);
+
+                IGF.setUnscopedLocalTypeData(
+                    archetype,
+                    LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
+                    table);
+              }
+
+              return /*finished?*/ false;
+            });
       }
       return;
     }
@@ -960,7 +995,10 @@
     return true;
   }
 
-  return false;
+  // Check if there are any conditional conformances. Other forms of conditional
+  // requirements don't exist in the witness table.
+  return SILWitnessTable::enumerateWitnessTableConditionalConformances(
+      conformance, [](unsigned, CanType, ProtocolDecl *) { return true; });
 }
 
 /// Detail about how an object conforms to a protocol.
@@ -977,23 +1015,73 @@
                                               CanType conformingType) const = 0;
 };
 
-static llvm::Value *
-emitWitnessTableAccessorCall(IRGenFunction &IGF,
-                             const NormalProtocolConformance *conformance,
-                             CanType conformingType,
-                             llvm::Value **srcMetadataCache) {
-  auto accessor =
-    IGF.IGM.getAddrOfWitnessTableAccessFunction(conformance, NotForDefinition);
+static std::pair<llvm::Value *, llvm::Value *>
+emitConditionalConformancesBuffer(IRGenFunction &IGF,
+                                  const ProtocolConformance *conformance) {
+  // Pointers to the witness tables, in the right order, which will be included
+  // in the buffer that gets passed to the witness table accessor.
+  llvm::SmallVector<llvm::Value *, 4> tables;
 
-  // If the conformance is generic, the accessor takes the metatype
-  // as an argument.
+  auto subMap = conformance->getSubstitutions(IGF.IGM.getSwiftModule());
+  auto rootConformance = conformance->getRootNormalConformance();
+
+  SILWitnessTable::enumerateWitnessTableConditionalConformances(
+      rootConformance, [&](unsigned, CanType type, ProtocolDecl *proto) {
+        auto substType = type.subst(subMap)->getCanonicalType();
+        auto reqConformance = subMap.lookupConformance(type, proto);
+        assert(reqConformance && "conditional conformance must exist");
+
+        tables.push_back(emitWitnessTableRef(IGF, substType, *reqConformance));
+        return /*finished?*/ false;
+      });
+
+  // No conditional requirements means no need for a buffer, and size == 0 means
+  // no reading of the pointer.
+  // FIXME(cond. conf. assert): once the dynamic assertion is removed from the
+  // instantiation function, we can have size as undef too.
+  if (tables.empty()) {
+    return {llvm::UndefValue::get(IGF.IGM.WitnessTablePtrPtrTy),
+            llvm::ConstantInt::get(IGF.IGM.SizeTy, 0)};
+  }
+
+  auto buffer = IGF.createAlloca(
+      llvm::ArrayType::get(IGF.IGM.WitnessTablePtrTy, tables.size()),
+      IGF.IGM.getPointerAlignment(), "conditional.requirement.buffer");
+  buffer = IGF.Builder.CreateStructGEP(buffer, 0, Size(0));
+
+  // Write each of the conditional witness tables into the buffer.
+  for (auto idx : indices(tables)) {
+    auto slot =
+        IGF.Builder.CreateConstArrayGEP(buffer, idx, IGF.IGM.getPointerSize());
+    IGF.Builder.CreateStore(tables[idx], slot);
+  }
+
+  auto count = llvm::ConstantInt::get(IGF.IGM.SizeTy, tables.size());
+  return {buffer.getAddress(), count};
+}
+
+static llvm::Value *emitWitnessTableAccessorCall(
+    IRGenFunction &IGF, const ProtocolConformance *conformance,
+    CanType conformingType, llvm::Value **srcMetadataCache) {
+  auto accessor = IGF.IGM.getAddrOfWitnessTableAccessFunction(
+      conformance->getRootNormalConformance(), NotForDefinition);
+
+  // If the conformance is generic, the accessor takes the metatype plus
+  // possible conditional conformances arguments.
   llvm::CallInst *call;
-  if (conformance->getDeclContext()->isGenericContext()) {
+  if (conformance->witnessTableAccessorRequiresArguments()) {
     // Emit the source metadata if we haven't yet.
     if (!*srcMetadataCache) {
       *srcMetadataCache = IGF.emitTypeMetadataRef(conformingType);
     }
-    call = IGF.Builder.CreateCall(accessor, {*srcMetadataCache});
+
+    llvm::Value *conditionalTables, *numConditionalTables;
+    std::tie(conditionalTables, numConditionalTables) =
+        emitConditionalConformancesBuffer(IGF, conformance);
+
+    call = IGF.Builder.CreateCall(
+        accessor, {*srcMetadataCache, conditionalTables, numConditionalTables});
+
   } else {
     call = IGF.Builder.CreateCall(accessor, {});
   }
@@ -1009,25 +1097,25 @@
 /// given type.
 static llvm::Function *
 getWitnessTableLazyAccessFunction(IRGenModule &IGM,
-                                  const NormalProtocolConformance *conformance,
+                                  const ProtocolConformance *conformance,
                                   CanType conformingType) {
   assert(!conformingType->hasArchetype());
-  llvm::Function *accessor =
-    IGM.getAddrOfWitnessTableLazyAccessFunction(conformance, conformingType,
-                                                ForDefinition);
+  auto rootConformance = conformance->getRootNormalConformance();
+  llvm::Function *accessor = IGM.getAddrOfWitnessTableLazyAccessFunction(
+      rootConformance, conformingType, ForDefinition);
 
   // If we're not supposed to define the accessor, or if we already
   // have defined it, just return the pointer.
   if (!accessor->empty())
     return accessor;
 
-  if (IGM.getOptions().OptimizeForSize)
+  if (IGM.getOptions().optimizeForSize())
     accessor->addFnAttr(llvm::Attribute::NoInline);
 
   // Okay, define the accessor.
-  auto cacheVariable = cast<llvm::GlobalVariable>(
-    IGM.getAddrOfWitnessTableLazyCacheVariable(conformance, conformingType,
-                                               ForDefinition));
+  auto cacheVariable =
+      cast<llvm::GlobalVariable>(IGM.getAddrOfWitnessTableLazyCacheVariable(
+          rootConformance, conformingType, ForDefinition));
   emitLazyCacheAccessFunction(IGM, accessor, cacheVariable,
                               [&](IRGenFunction &IGF) -> llvm::Value* {
     llvm::Value *conformingMetadataCache = nullptr;
@@ -1046,8 +1134,8 @@
 
   const NormalProtocolConformance *RootConformance;
 public:
-  DirectConformanceInfo(const NormalProtocolConformance *C)
-    : RootConformance(C) {}
+  DirectConformanceInfo(const ProtocolConformance *C)
+      : RootConformance(C->getRootNormalConformance()) {}
 
   llvm::Value *getTable(IRGenFunction &IGF, CanType conformingType,
                         llvm::Value **conformingMetadataCache) const override {
@@ -1064,10 +1152,10 @@
 class AccessorConformanceInfo : public ConformanceInfo {
   friend ProtocolInfo;
 
-  const NormalProtocolConformance *Conformance;
+  const ProtocolConformance *Conformance;
+
 public:
-  AccessorConformanceInfo(const NormalProtocolConformance *C)
-    : Conformance(C) {}
+  AccessorConformanceInfo(const ProtocolConformance *C) : Conformance(C) {}
 
   llvm::Value *getTable(IRGenFunction &IGF, CanType type,
                         llvm::Value **typeMetadataCache) const override {
@@ -1102,27 +1190,29 @@
     CanType ConcreteType;
     const NormalProtocolConformance &Conformance;
     ArrayRef<SILWitnessTable::Entry> SILEntries;
+    ArrayRef<SILWitnessTable::ConditionalConformance>
+        SILConditionalConformances;
     const ProtocolInfo &PI;
     Optional<FulfillmentMap> Fulfillments;
     SmallVector<std::pair<size_t, const ConformanceInfo *>, 4>
       SpecializedBaseConformances;
-    // Metadata caches are stored at negative offsets.
-    unsigned NextCacheIndex = 0;
+
+    SmallVector<size_t, 4> ConditionalRequirementPrivateDataIndices;
+
+    // Conditional conformances and metadata caches are stored at negative
+    // offsets, with conditional conformances closest to 0.
+    unsigned NextPrivateDataIndex = 0;
     bool RequiresSpecialization = false;
 
   public:
-    WitnessTableBuilder(IRGenModule &IGM,
-                        ConstantArrayBuilder &table,
+    WitnessTableBuilder(IRGenModule &IGM, ConstantArrayBuilder &table,
                         SILWitnessTable *SILWT)
-      : IGM(IGM), Table(table),
-        ConcreteType(SILWT->getConformance()->getType()->getCanonicalType()),
-        Conformance(*SILWT->getConformance()),
-        SILEntries(SILWT->getEntries()),
-        PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol()))
-    {
-      // TODO: in conditional conformances, allocate space for the assumed
-      // conformances here.
-
+        : IGM(IGM), Table(table),
+          ConcreteType(SILWT->getConformance()->getType()->getCanonicalType()),
+          Conformance(*SILWT->getConformance()),
+          SILEntries(SILWT->getEntries()),
+          SILConditionalConformances(SILWT->getConditionalConformances()),
+          PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol())) {
       // If the conformance is resilient, we require runtime instantiation.
       if (isResilientConformance(&Conformance))
         RequiresSpecialization = true;
@@ -1144,8 +1234,8 @@
       assert(entry.getBaseProtocolWitness().Requirement == baseProto
              && "sil witness table does not match protocol");
       auto piIndex = PI.getBaseIndex(baseProto);
-      assert(piIndex.getValue() == Table.size()
-             && "offset doesn't match ProtocolInfo layout");
+      assert((size_t)piIndex.getValue() == Table.size() &&
+             "offset doesn't match ProtocolInfo layout");
 #endif
       
       SILEntries = SILEntries.slice(1);
@@ -1189,8 +1279,8 @@
              && "sil witness table does not match protocol");
       auto piIndex =
         PI.getFunctionIndex(cast<AbstractFunctionDecl>(requirement.getDecl()));
-      assert(piIndex.getValue() == Table.size()
-             && "offset doesn't match ProtocolInfo layout");
+      assert((size_t)piIndex.getValue() == Table.size() &&
+             "offset doesn't match ProtocolInfo layout");
 #endif
 
       SILFunction *Func = entry.getMethodWitness().Witness;
@@ -1220,8 +1310,8 @@
                == requirement.getAssociation()
              && "sil witness table does not match protocol");
       auto piIndex = PI.getAssociatedTypeIndex(requirement);
-      assert(piIndex.getValue() == Table.size()
-             && "offset doesn't match ProtocolInfo layout");
+      assert((size_t)piIndex.getValue() == Table.size() &&
+             "offset doesn't match ProtocolInfo layout");
 #endif
 
       SILEntries = SILEntries.slice(1);
@@ -1263,13 +1353,13 @@
                requirement.getAssociatedRequirement()
              && "sil witness table does not match protocol");
       auto piIndex = PI.getAssociatedConformanceIndex(requirement);
-      assert(piIndex.getValue() == Table.size()
-             && "offset doesn't match ProtocolInfo layout");
+      assert((size_t)piIndex.getValue() == Table.size() &&
+             "offset doesn't match ProtocolInfo layout");
 #endif
 
       SILEntries = SILEntries.slice(1);
 
-      llvm::Constant *wtableAccessFunction = 
+      llvm::Constant *wtableAccessFunction =
         getAssociatedTypeWitnessTableAccessFunction(requirement,
                                                     associate,
                                                     associatedConformance);
@@ -1277,6 +1367,17 @@
     }
 
   private:
+    void addConditionalConformances() {
+      for (auto conditional : SILConditionalConformances) {
+        // We don't actually need to know anything about the specific
+        // conformances here, just make sure we get right private data slots.
+        (void)conditional;
+
+        auto reqtIndex = getNextPrivateDataIndex();
+        ConditionalRequirementPrivateDataIndices.push_back(reqtIndex);
+      }
+    }
+
     llvm::Constant *buildInstantiationFunction();
 
     llvm::Constant *
@@ -1295,9 +1396,16 @@
                                     llvm::function_ref<llvm::Value*()> body);
 
     /// Allocate another word of private data storage in the conformance table.
-    unsigned getNextCacheIndex() {
+    unsigned getNextPrivateDataIndex() {
       RequiresSpecialization = true;
-      return NextCacheIndex++;
+      return NextPrivateDataIndex++;
+    }
+
+    Address getAddressOfPrivateDataSlot(IRGenFunction &IGF, Address table,
+                                        unsigned index) {
+      assert(index < NextPrivateDataIndex);
+      return IGF.Builder.CreateConstArrayGEP(
+          table, privateIndexToTableOffset(index), IGF.IGM.getPointerSize());
     }
 
     const FulfillmentMap &getFulfillmentMap() {
@@ -1336,6 +1444,7 @@
 
 /// Build the witness table.
 void WitnessTableBuilder::build() {
+  addConditionalConformances();
   visitProtocolDecl(Conformance.getProtocol());
   TableSize = Table.size();
 }
@@ -1355,7 +1464,7 @@
   llvm::Function *accessor =
     IGM.getAddrOfAssociatedTypeMetadataAccessFunction(&Conformance,
                                                       requirement);
-  if (IGM.getOptions().OptimizeForSize)
+  if (IGM.getOptions().optimizeForSize())
     accessor->addFnAttr(llvm::Attribute::NoInline);
 
   IRGenFunction IGF(IGM, accessor);
@@ -1421,15 +1530,11 @@
   // and won't let us re-use the cache with other non-dependent uses in
   // the module.  Therefore, in this case, we use the address of the lazy-cache
   // function.
-  //
-  // FIXME: we will need to pass additional parameters if the target
-  // conformance is conditional.
   auto rootConformance = conformance->getRootNormalConformance();
-  if (rootConformance->getDeclContext()->isGenericContext()) {
+  if (rootConformance->witnessTableAccessorRequiresArguments()) {
     return getWitnessTableLazyAccessFunction(IGM, rootConformance, type);
   } else {
-    return IGM.getAddrOfWitnessTableAccessFunction(
-                                    conformance->getRootNormalConformance(),
+    return IGM.getAddrOfWitnessTableAccessFunction(rootConformance,
                                                    NotForDefinition);
   }
 }
@@ -1465,7 +1570,7 @@
   if (IGM.DebugInfo)
     IGM.DebugInfo->emitArtificialFunction(IGF, accessor);
 
-  if (IGM.getOptions().OptimizeForSize)
+  if (IGM.getOptions().optimizeForSize())
     accessor->addFnAttr(llvm::Attribute::NoInline);
 
   Explosion parameters = IGF.collectParameters();
@@ -1554,9 +1659,8 @@
                                  llvm::Value *selfMetadata,
                                  llvm::function_ref<llvm::Value*()> body) {
   // Allocate a new cache slot and drill down to it.
-  int cacheIndex = -1 - getNextCacheIndex();
-  Address cache = IGF.Builder.CreateConstArrayGEP(destTable, cacheIndex,
-                                                  IGM.getPointerSize());
+  auto cache =
+      getAddressOfPrivateDataSlot(IGF, destTable, getNextPrivateDataIndex());
 
   llvm::Type *expectedTy = IGF.CurFn->getReturnType();
   cache = IGF.Builder.CreateBitCast(cache, expectedTy->getPointerTo());
@@ -1620,11 +1724,18 @@
 
   Explosion params = IGF.collectParameters();
   llvm::Value *metadata;
+  llvm::Value *conditionalReqtWtables;
+  llvm::Value *numConditionalReqtWtables;
 
-  if (Conformance.getDeclContext()->isGenericContext())
+  if (Conformance.witnessTableAccessorRequiresArguments()) {
     metadata = params.claimNext();
-  else
+    conditionalReqtWtables = params.claimNext();
+    numConditionalReqtWtables = params.claimNext();
+  } else {
     metadata = llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy);
+    conditionalReqtWtables = nullptr;
+    numConditionalReqtWtables = llvm::ConstantInt::get(IGF.IGM.SizeTy, 0);
+  }
 
   // Okay, we need a cache.  Build the cache structure.
   //  struct GenericWitnessTable {
@@ -1641,7 +1752,8 @@
   //    RelativeDirectPointer<WitnessTable> WitnessTable;
   //
   //    /// The instantiation function, which is called after the template is copied.
-  //    RelativeDirectPointer<void(WitnessTable *, const Metadata *)> Instantiator;
+  //    RelativeDirectPointer<void(WitnessTable *, const Metadata *, void * const *)>
+  //                               Instantiator;
   //
   //    void *PrivateData[swift::NumGenericMetadataPrivateDataWords];
   //  };
@@ -1655,7 +1767,8 @@
   // is non-dependent.
   // TODO: the conformance might be conditional.
   llvm::Constant *instantiationFn;
-  if (SpecializedBaseConformances.empty()) {
+  if (SpecializedBaseConformances.empty() &&
+      ConditionalRequirementPrivateDataIndices.empty()) {
     instantiationFn = nullptr;
   } else {
     instantiationFn = buildInstantiationFunction();
@@ -1672,7 +1785,7 @@
   // WitnessTableSizeInWords
   cacheData.addInt(IGM.Int16Ty, TableSize);
   // WitnessTablePrivateSizeInWords
-  cacheData.addInt(IGM.Int16Ty, NextCacheIndex);
+  cacheData.addInt(IGM.Int16Ty, NextPrivateDataIndex);
   // RelativeIndirectablePointer<ProtocolDescriptor>
   cacheData.addRelativeAddress(descriptorRef);
   // RelativePointer<WitnessTable>
@@ -1694,10 +1807,31 @@
   cacheData.finishAndSetAsInitializer(cache);
   cache->setConstant(true);
 
-  llvm::Value *instantiationArgs =
-    llvm::ConstantPointerNull::get(IGM.Int8PtrPtrTy);
-  auto call = IGF.Builder.CreateCall(IGM.getGetGenericWitnessTableFn(),
-                                     { cache, metadata, instantiationArgs });
+  // Create the slice structure for the conditional conformances, which is
+  // passed as the last argument to the instantiation function.
+  // FIXME(cond. conf. assert): Elide this local/replace it with `undef` once
+  // the size assertion in the instantiation function is gone.
+  auto conditionalSlice =
+      IGF.createAlloca(IGF.IGM.WitnessTableSliceTy,
+                       IGF.IGM.getPointerAlignment(), "conditional.tables");
+
+  // Only store a pointer if it will be read. If not (i.e. size == 0/this
+  // conformance is unconditional), we can leave it as undef.
+  if (conditionalReqtWtables) {
+    auto tableSlot = IGF.Builder.CreateStructGEP(conditionalSlice, 0, Size(0));
+    IGF.Builder.CreateStore(conditionalReqtWtables, tableSlot);
+  }
+
+  auto sizeSlot = IGF.Builder.CreateStructGEP(conditionalSlice, 1,
+                                              Size(IGF.IGM.getPointerSize()));
+  IGF.Builder.CreateStore(numConditionalReqtWtables, sizeSlot);
+
+  auto instantiationArgs =
+      IGF.Builder.CreateBitCast(conditionalSlice, IGM.Int8PtrPtrTy);
+
+  auto call =
+      IGF.Builder.CreateCall(IGM.getGetGenericWitnessTableFn(),
+                             {cache, metadata, instantiationArgs.getAddress()});
   call->setDoesNotThrow();
 
   IGF.Builder.CreateRet(call);
@@ -1710,32 +1844,82 @@
   if (IGM.DebugInfo)
     IGM.DebugInfo->emitArtificialFunction(IGF, fn);
 
+  auto PointerAlignment = IGM.getPointerAlignment();
+  auto PointerSize = IGM.getPointerSize();
+
   // Break out the parameters.
   Explosion params = IGF.collectParameters();
-  Address wtable(params.claimNext(), IGM.getPointerAlignment());
+  Address wtable(params.claimNext(), PointerAlignment);
   llvm::Value *metadata = params.claimNext();
-  llvm::Value *instantiationArgs = params.claimNext();
-  (void) instantiationArgs; // unused for now
+  Address instantiationArgs(params.claimNext(), PointerAlignment);
 
-  // TODO: store any required conditional-conformance information
-  // in the private data.
+  // The details of any conditional conformances are in the last argument, as a
+  // pointer/size pair.
+  auto conditionalTablesSlice = IGF.Builder.CreateElementBitCast(
+      instantiationArgs, IGF.IGM.WitnessTableSliceTy);
+
+  auto conditionalTablesPtr =
+      IGF.Builder.CreateStructGEP(conditionalTablesSlice, 0, Size(0));
+  Address conditionalTables(IGF.Builder.CreateLoad(conditionalTablesPtr),
+                            PointerAlignment);
+
+  auto numConditionalTablesPtr =
+    IGF.Builder.CreateStructGEP(conditionalTablesSlice, 1, Size(PointerSize));
+  auto numConditionalTables = IGF.Builder.CreateLoad(numConditionalTablesPtr);
+
+  // Assert that the number of witness tables passed in is the number required
+  // for the conditional conformances of this witness table.
+
+  // FIXME(cond. conf. assert): remove this once we're confident in conditional
+  // conformances and especially dynamic casting. (Look for the other
+  // 'cond. conf. assert' FIXMEs too.)
+  auto failBB = IGF.createBasicBlock("bad_witness_table_count");
+  auto contBB = IGF.createBasicBlock("cont");
+
+  auto cmp = IGF.Builder.CreateICmpEQ(
+      numConditionalTables,
+      llvm::ConstantInt::get(IGM.SizeTy,
+                             ConditionalRequirementPrivateDataIndices.size()));
+  IGF.Builder.CreateCondBr(cmp, contBB, failBB);
+
+  // All good: now we can actually fill in the witness table.
+  IGF.Builder.emitBlock(contBB);
 
   // Initialize all the specialized base conformances.
   for (auto &base : SpecializedBaseConformances) {
     // Ask the ConformanceInfo to emit the wtable.
-    // TODO: we may need to bind extra information in the IGF in order
-    // to make conditional conformances work.
     llvm::Value *baseWTable =
       base.second->getTable(IGF, ConcreteType, &metadata);
     baseWTable = IGF.Builder.CreateBitCast(baseWTable, IGM.Int8PtrTy);
 
     // Store that to the appropriate slot in the new witness table.
-    Address slot = IGF.Builder.CreateConstArrayGEP(wtable, base.first,
-                                                   IGM.getPointerSize());
+    Address slot =
+        IGF.Builder.CreateConstArrayGEP(wtable, base.first, PointerSize);
     IGF.Builder.CreateStore(baseWTable, slot);
   }
 
+  /// Run through the conditional conformance witness tables, pulling them out
+  /// of the slice and putting them into the private data of the witness table.
+  for (auto idx : indices(ConditionalRequirementPrivateDataIndices)) {
+    Address conditionalTablePtr =
+        IGF.Builder.CreateConstArrayGEP(conditionalTables, idx, PointerSize);
+    Address slot = getAddressOfPrivateDataSlot(
+        IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
+    auto conditionalTable = IGF.Builder.CreateLoad(conditionalTablePtr);
+    auto coercedSlot =
+        IGF.Builder.CreateElementBitCast(slot, conditionalTable->getType());
+    IGF.Builder.CreateStore(conditionalTable, coercedSlot);
+  }
+
   IGF.Builder.CreateRetVoid();
+
+  // The counts didn't match; abort.
+  IGF.Builder.emitBlock(failBB);
+  llvm::Function *trapIntrinsic =
+      llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
+  IGF.Builder.CreateCall(trapIntrinsic, {});
+  IGF.Builder.CreateUnreachable();
+
   return fn;
 }
 
@@ -1787,28 +1971,40 @@
   assert(conformance->getProtocol() == protocol &&
          "conformance is for wrong protocol");
 
-  // Drill down to the root normal conformance.
+  auto checkCache =
+      [&](const ProtocolConformance *conf) -> Optional<ConformanceInfo *> {
+    // Check whether we've already cached this.
+    auto it = Conformances.find(conformance);
+    if (it != Conformances.end())
+      return it->second;
+
+    return None;
+  };
+
+  if (auto found = checkCache(conformance))
+    return **found;
+
+  //  Drill down to the root normal
   auto normalConformance = conformance->getRootNormalConformance();
 
-  // Check whether we've already cached this.
-  auto it = Conformances.find(normalConformance);
-  if (it != Conformances.end()) return *it->second;
-
   ConformanceInfo *info;
-
   // If the conformance is dependent in any way, we need to unique it.
   // TODO: maybe this should apply whenever it's out of the module?
   // TODO: actually enable this
   if (isDependentConformance(IGM, normalConformance,
                              ResilienceExpansion::Maximal)) {
-    info = new AccessorConformanceInfo(normalConformance);
-
-  // Otherwise, we can use a direct-referencing conformance.
+    info = new AccessorConformanceInfo(conformance);
+    Conformances.insert({conformance, info});
   } else {
+    // Otherwise, we can use a direct-referencing conformance, which can get
+    // away with the non-specialized conformance.
+    if (auto found = checkCache(normalConformance))
+      return **found;
+
     info = new DirectConformanceInfo(normalConformance);
+    Conformances.insert({normalConformance, info});
   }
 
-  Conformances.insert({normalConformance, info});
   return *info;
 }
 
@@ -2177,6 +2373,41 @@
     return source;
   }
 
+  case Component::Kind::ConditionalConformance: {
+    auto sourceConformance = sourceKey.Kind.getProtocolConformance();
+
+    auto reqtIndex = component.getPrimaryIndex();
+
+    ProtocolDecl *conformingProto;
+    auto found = SILWitnessTable::enumerateWitnessTableConditionalConformances(
+        sourceConformance.getConcrete(),
+        [&](unsigned index, CanType type, ProtocolDecl *proto) {
+          if (reqtIndex == index) {
+            conformingProto = proto;
+            sourceKey.Type = type;
+            // done!
+            return true;
+          }
+          return /*finished?*/ false;
+        });
+    assert(found && "too many conditional conformances");
+
+    sourceKey.Kind =
+        LocalTypeDataKind::forAbstractProtocolWitnessTable(conformingProto);
+
+    if (source) {
+      WitnessIndex index(privateIndexToTableOffset(reqtIndex),
+                         /*prefix*/ false);
+
+      source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
+      source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
+      setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
+                                  conformingProto);
+    }
+
+    return source;
+  }
+
   case Component::Kind::Impossible:
     llvm_unreachable("following an impossible path!");
 
@@ -2207,6 +2438,9 @@
       out << "nominal_type_argument_conformance["
           << component.getPrimaryIndex() << "]";
       break;
+    case Component::Kind::ConditionalConformance:
+      out << "conditional_conformance[" << component.getPrimaryIndex() << "]";
+      break;
     case Component::Kind::Impossible:
       out << "impossible";
       break;
@@ -2594,8 +2828,10 @@
   auto generics = ncGenerics->getCanonicalSignature();
   CanSILFunctionType fnType = [&]() -> CanSILFunctionType {
     return SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
+                                SILCoroutineKind::None,
                                 /*callee*/ ParameterConvention::Direct_Unowned,
-                                /*params*/ {}, /*results*/ {}, /*error*/ None,
+                                /*params*/ {}, /*yields*/ {},
+                                /*results*/ {}, /*error*/ None,
                                 IGM.Context);
   }();
 
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index 50f37d2..cfc0e81 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -1636,6 +1636,8 @@
     return convertBlockStorageType(cast<SILBlockStorageType>(ty));
   case TypeKind::SILBox:
     return convertBoxType(cast<SILBoxType>(ty));
+  case TypeKind::SILToken:
+    llvm_unreachable("should not be asking for representation of a SILToken");
   }
   }
   llvm_unreachable("bad type kind");
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 348ceb8..fe7ac34 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -242,8 +242,8 @@
         buffer.getAlignment());
     auto *boxStart = IGF.Builder.CreateLoad(boxAddress);
     auto *alignmentMask = type.getAlignmentMask(IGF, T);
-    auto *heapHeaderSize =
-        llvm::ConstantInt::get(IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+    auto *heapHeaderSize = llvm::ConstantInt::get(
+        IGM.SizeTy, IGM.RefCountedStructSize.getValue());
     auto *startOffset =
         Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
                           Builder.CreateNot(alignmentMask));
@@ -820,7 +820,7 @@
         IGF.Builder.CreateStore(ptr, dest);
         auto *alignmentMask = fixedTI.getStaticAlignmentMask(IGM);
         auto *heapHeaderSize = llvm::ConstantInt::get(
-            IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+            IGM.SizeTy, IGM.RefCountedStructSize.getValue());
         auto *startOffset = IGF.Builder.CreateAnd(
             IGF.Builder.CreateAdd(heapHeaderSize, alignmentMask),
             IGF.Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 6861c81..ec76528 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -158,7 +158,7 @@
   // Set up a pipeline.
   PassManagerBuilderWrapper PMBuilder(Opts);
 
-  if (Opts.Optimize && !Opts.DisableLLVMOptzns) {
+  if (Opts.shouldOptimize() && !Opts.DisableLLVMOptzns) {
     PMBuilder.OptLevel = 2; // -Os
     PMBuilder.SizeLevel = 1; // -Os
     PMBuilder.Inliner = llvm::createFunctionInliningPass(200);
@@ -455,7 +455,7 @@
   // rely on any other LLVM ARC transformations, but we do need ARC
   // contraction to add the objc_retainAutoreleasedReturnValue
   // assembly markers and remove clang.arc.used.
-  if (Opts.Optimize && !DisableObjCARCContract)
+  if (Opts.shouldOptimize() && !DisableObjCARCContract)
     EmitPasses.add(createObjCARCContractPass());
 
   // Set up the final emission passes.
@@ -524,8 +524,9 @@
     return nullptr;
   }
 
-  CodeGenOpt::Level OptLevel = Opts.Optimize ? CodeGenOpt::Default // -Os
-                                             : CodeGenOpt::None;
+  CodeGenOpt::Level OptLevel = (Opts.shouldOptimize() ?
+                                  CodeGenOpt::Default // -Os
+                                  : CodeGenOpt::None);
 
   // Set up TargetOptions and create the target features string.
   TargetOptions TargetOpts;
@@ -684,7 +685,7 @@
 /// IRGenModule.
 static void runIRGenPreparePasses(SILModule &Module,
                                   irgen::IRGenModule &IRModule) {
-  SILPassManager PM(&Module, &IRModule);
+  SILPassManager PM(&Module, &IRModule, "irgen", /*isMandatoryPipeline=*/ true);
   bool largeLoadable = Module.getOptions().EnableLargeLoadableTypes;
 #define PASS(ID, Tag, Name)
 #define IRGEN_PASS(ID, Tag, Name)                                              \
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 9907fd4..1f35073 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -45,6 +45,7 @@
 #include "llvm/Config/config.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -275,31 +276,6 @@
     return false;
   }
 
-  /// Determine whether this location is some kind of closure.
-  static bool isAbstractClosure(const SILLocation &Loc) {
-    if (Expr *E = Loc.getAsASTNode<Expr>())
-      if (isa<AbstractClosureExpr>(E))
-        return true;
-    return false;
-  }
-
-  /// Both the code that is used to set up a closure object and the
-  /// (beginning of) the closure itself has the AbstractClosureExpr as
-  /// location. We are only interested in the latter case and want to
-  /// ignore the setup code.
-  ///
-  /// callWithClosure(
-  ///  { // <-- a breakpoint here should only stop inside of the closure.
-  ///    foo();
-  ///  })
-  ///
-  /// The actual closure has a closure expression as scope.
-  static bool shouldIgnoreAbstractClosure(Optional<SILLocation> Loc,
-                                          const SILDebugScope *DS) {
-    return Loc && isAbstractClosure(*Loc) && DS &&
-           !isAbstractClosure(DS->Loc) && !Loc->is<ImplicitReturnLocation>();
-  }
-
   llvm::MDNode *createInlinedAt(const SILDebugScope *DS) {
     auto *CS = DS->InlinedCallSite;
     if (!CS)
@@ -1358,6 +1334,7 @@
     case TypeKind::Module:
     case TypeKind::SILBlockStorage:
     case TypeKind::SILBox:
+    case TypeKind::SILToken:
     case TypeKind::BuiltinUnsafeValueBuffer:
 
       DEBUG(llvm::errs() << "Unhandled type: "; DbgTy.getType()->dump();
@@ -1502,7 +1479,6 @@
   unsigned Lang = llvm::dwarf::DW_LANG_Swift;
   std::string Producer = version::getSwiftFullVersion(
       IGM.Context.LangOpts.EffectiveLanguageVersion);
-  bool IsOptimized = Opts.Optimize;
   StringRef Flags = Opts.DWARFDebugFlags;
   unsigned Major, Minor;
   std::tie(Major, Minor) = version::getSwiftNumericVersion();
@@ -1514,7 +1490,7 @@
   // Clang is doing the same thing here.
   TheCU = DBuilder.createCompileUnit(
       Lang, DBuilder.createFile(AbsMainFile, Opts.DebugCompilationDir),
-      Producer, IsOptimized, Flags, MajorRuntimeVersion, SplitName,
+      Producer, Opts.shouldOptimize(), Flags, MajorRuntimeVersion, SplitName,
       Opts.DebugInfoKind > IRGenDebugInfoKind::LineTables
           ? llvm::DICompileUnit::FullDebug
           : llvm::DICompileUnit::LineTablesOnly);
@@ -1597,7 +1573,7 @@
   SILFunction *Fn = DS->getInlinedFunction();
   SILLocation::DebugLoc L;
 
-  if (shouldIgnoreAbstractClosure(Loc, DS) || (Fn && Fn->isThunk())) {
+  if ((Loc && Loc->isAutoGenerated()) || (Fn && Fn->isThunk())) {
     // Reuse the last source location if we are still in the same
     // scope to get a more contiguous line table.
     // Otherwise use a line 0 artificial location.
@@ -1827,7 +1803,6 @@
   // Various flags.
   bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
   bool IsDefinition = true;
-  bool IsOptimized = Opts.Optimize;
   llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
 
   // Mark everything that is not visible from the source code (i.e.,
@@ -1862,7 +1837,7 @@
   // Construct the DISubprogram.
   llvm::DISubprogram *SP = DBuilder.createFunction(
       Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
-      ScopeLine, Flags, IsOptimized, TemplateParameters, Decl, Error);
+      ScopeLine, Flags, Opts.shouldOptimize(), TemplateParameters, Decl, Error);
 
   if (Fn && !Fn->isDeclaration())
     Fn->setSubprogram(SP);
@@ -2002,7 +1977,7 @@
   auto *BB = Builder.GetInsertBlock();
 
   // An alloca may only be described by exactly one dbg.declare.
-  if (isa<llvm::AllocaInst>(Storage) && llvm::FindAllocaDbgDeclare(Storage))
+  if (isa<llvm::AllocaInst>(Storage) && !llvm::FindDbgAddrUses(Storage).empty())
     return;
 
   // A dbg.declare is only meaningful if there is a single alloca for
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 3dd914d..d9e5e78 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -32,10 +32,12 @@
 using namespace irgen;
 
 IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn,
+                             OptimizationMode OptMode,
                              const SILDebugScope *DbgScope,
                              Optional<SILLocation> DbgLoc)
     : IGM(IGM), Builder(IGM.getLLVMContext(),
                         IGM.DebugInfo && !IGM.Context.LangOpts.DebuggerSupport),
+      OptMode(OptMode),
       CurFn(Fn), DbgScope(DbgScope), inOutlinedFunction(false) {
 
   // Make sure the instructions in this function are attached its debug scope.
@@ -60,6 +62,13 @@
   if (LocalTypeData) destroyLocalTypeData();
 }
 
+OptimizationMode IRGenFunction::getEffectiveOptimizationMode() const {
+  if (OptMode != OptimizationMode::NotSet)
+    return OptMode;
+
+  return IGM.getOptions().OptMode;
+}
+
 ModuleDecl *IRGenFunction::getSwiftModule() const {
   return IGM.getSwiftModule();
 }
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 507cddb..8d46cbf 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -66,6 +66,10 @@
   IRGenModule &IGM;
   IRBuilder Builder;
 
+  /// If != OptimizationMode::NotSet, the optimization mode specified with an
+  /// function attribute.
+  OptimizationMode OptMode;
+
   llvm::Function *CurFn;
   ModuleDecl *getSwiftModule() const;
   SILModule &getSILModule() const;
@@ -73,6 +77,7 @@
   const IRGenOptions &getOptions() const;
 
   IRGenFunction(IRGenModule &IGM, llvm::Function *fn,
+                OptimizationMode Mode = OptimizationMode::NotSet,
                 const SILDebugScope *DbgScope = nullptr,
                 Optional<SILLocation> DbgLoc = None);
   ~IRGenFunction();
@@ -111,6 +116,16 @@
 
 //--- Helper methods -----------------------------------------------------------
 public:
+
+  /// Returns the optimization mode for the function. If no mode is set for the
+  /// function, returns the global mode, i.e. the mode in IRGenOptions.
+  OptimizationMode getEffectiveOptimizationMode() const;
+
+  /// Returns true if this function should be optimized for size.
+  bool optimizeForSize() const {
+    return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+  }
+
   Address createAlloca(llvm::Type *ty, Alignment align,
                        const llvm::Twine &name);
   Address createAlloca(llvm::Type *ty, llvm::Value *ArraySize, Alignment align,
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index b931047..e973c4f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -88,7 +88,7 @@
   auto &ClangContext = Importer->getClangASTContext();
 
   auto &CGO = Importer->getClangCodeGenOpts();
-  CGO.OptimizationLevel = Opts.Optimize ? 3 : 0;
+  CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0;
   CGO.DisableFPElim = Opts.DisableFPElim;
   CGO.DiscardValueNames = !Opts.shouldProvideValueNames();
   switch (Opts.DebugInfoKind) {
@@ -264,8 +264,11 @@
   });
   FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS);
 
-  llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, Int32Ty, Int32Ty};
+  // This must match struct HeapObject in the runtime.
+  llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, IntPtrTy};
   RefCountedStructTy->setBody(refCountedElts);
+  RefCountedStructSize =
+    Size(DataLayout.getStructLayout(RefCountedStructTy)->getSizeInBytes());
 
   PtrSize = Size(DataLayout.getPointerSize(DefaultAS));
 
@@ -365,6 +368,10 @@
                                               /*packed*/ false);
   OpenedErrorTriplePtrTy = OpenedErrorTripleTy->getPointerTo(DefaultAS);
 
+  WitnessTablePtrPtrTy = WitnessTablePtrTy->getPointerTo(DefaultAS);
+  WitnessTableSliceTy = createStructType(*this, "swift.witness_table_slice",
+                                         {WitnessTablePtrPtrTy, SizeTy});
+
   InvariantMetadataID = LLVMContext.getMDKindID("invariant.load");
   InvariantNode = llvm::MDNode::get(LLVMContext, {});
   DereferenceableID = LLVMContext.getMDKindID("dereferenceable");
@@ -811,7 +818,8 @@
 }
 
 /// Construct initial function attributes from options.
-void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs) {
+void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+                                               OptimizationMode FuncOptMode) {
   // Add DisableFPElim. 
   if (!IRGen.Opts.DisableFPElim) {
     Attrs.addAttribute("no-frame-pointer-elim", "false");
@@ -844,7 +852,9 @@
     });
     Attrs.addAttribute("target-features", allFeatures);
   }
-  if (IRGen.Opts.OptimizeForSize)
+  if (FuncOptMode == OptimizationMode::NotSet)
+    FuncOptMode = IRGen.Opts.OptMode;
+  if (FuncOptMode == OptimizationMode::ForSize)
     Attrs.addAttribute(llvm::Attribute::MinSize);
 }
 
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index b242a31..6471f3e 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -24,6 +24,7 @@
 #include "swift/Basic/LLVM.h"
 #include "swift/Basic/ClusteredBitVector.h"
 #include "swift/Basic/SuccessorMap.h"
+#include "swift/Basic/OptimizationMode.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Hashing.h"
@@ -446,6 +447,7 @@
     llvm::PointerType *WitnessTablePtrTy;
   };
   llvm::StructType *RefCountedStructTy;/// %swift.refcounted = type { ... }
+  Size RefCountedStructSize;     /// sizeof(%swift.refcounted)
   llvm::PointerType *RefCountedPtrTy;  /// %swift.refcounted*
   llvm::PointerType *WeakReferencePtrTy;/// %swift.weak_reference*
   llvm::PointerType *UnownedReferencePtrTy;/// %swift.unowned_reference*
@@ -491,6 +493,8 @@
   llvm::PointerType *ErrorPtrTy;       /// %swift.error*
   llvm::StructType *OpenedErrorTripleTy; /// { %swift.opaque*, %swift.type*, i8** }
   llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }*
+  llvm::PointerType *WitnessTablePtrPtrTy;   /// i8***
+  llvm::StructType *WitnessTableSliceTy;     /// { witness_table**, i64 }
 
   /// Used to create unique names for class layout types with tail allocated
   /// elements.
@@ -954,7 +958,9 @@
   /// invalid.
   bool finalize();
 
-  void constructInitialFnAttributes(llvm::AttrBuilder &Attrs);
+  void constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+                                    OptimizationMode FuncOptMode =
+                                      OptimizationMode::NotSet);
   llvm::AttributeList constructInitialAttributes();
 
   void emitProtocolDecl(ProtocolDecl *D);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 6656db0..8d12c00 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -593,7 +593,7 @@
   /// expression depending on the value in the blocks dominated by the
   /// value.
   void emitDebugVariableRangeExtension(const SILBasicBlock *CurBB) {
-    if (IGM.IRGen.Opts.Optimize)
+    if (IGM.IRGen.Opts.shouldOptimize())
       return;
     for (auto &Variable : ValueDomPoints) {
       auto VarDominancePoint = Variable.second;
@@ -671,7 +671,7 @@
                               Alignment Align = Alignment(0)) {
     auto Ty = Storage->getType();
     // Never emit shadow copies when optimizing, or if already on the stack.
-    if (IGM.IRGen.Opts.Optimize ||
+    if (IGM.IRGen.Opts.shouldOptimize() ||
         isa<llvm::AllocaInst>(Storage) ||
         isa<llvm::UndefValue>(Storage) ||
         Ty == IGM.RefCountedPtrTy) // No debug info is emitted for refcounts.
@@ -710,7 +710,7 @@
                       StringRef Name, unsigned ArgNo,
                       llvm::SmallVectorImpl<llvm::Value *> &copy) {
     // Only do this at -O0.
-    if (IGM.IRGen.Opts.Optimize) {
+    if (IGM.IRGen.Opts.shouldOptimize()) {
       copy.append(vals.begin(), vals.end());
       return;
     }
@@ -776,7 +776,7 @@
 
     auto runtimeTy = getRuntimeReifiedType(IGM,
                                            Ty.getType()->getCanonicalType());
-    if (!IGM.IRGen.Opts.Optimize && runtimeTy->hasArchetype())
+    if (!IGM.IRGen.Opts.shouldOptimize() && runtimeTy->hasArchetype())
       runtimeTy.visit([&](CanType t) {
         if (auto archetype = dyn_cast<ArchetypeType>(t))
           emitTypeMetadataRef(archetype);
@@ -1018,12 +1018,18 @@
   void visitIndexAddrInst(IndexAddrInst *i);
   void visitTailAddrInst(TailAddrInst *i);
   void visitIndexRawPointerInst(IndexRawPointerInst *i);
+
+  void visitBeginApplyInst(BeginApplyInst *i);
+  void visitEndApplyInst(EndApplyInst *i);
+  void visitAbortApplyInst(AbortApplyInst *i);
   
   void visitUnreachableInst(UnreachableInst *i);
   void visitBranchInst(BranchInst *i);
   void visitCondBranchInst(CondBranchInst *i);
   void visitReturnInst(ReturnInst *i);
   void visitThrowInst(ThrowInst *i);
+  void visitUnwindInst(UnwindInst *i);
+  void visitYieldInst(YieldInst *i);
   void visitSwitchValueInst(SwitchValueInst *i);
   void visitSwitchEnumInst(SwitchEnumInst *i);
   void visitSwitchEnumAddrInst(SwitchEnumAddrInst *i);
@@ -1103,6 +1109,7 @@
 IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM,
                                    SILFunction *f)
   : IRGenFunction(IGM, IGM.getAddrOfSILFunction(f, ForDefinition),
+                  f->getOptimizationMode(),
                   f->getDebugScope(), f->getLocation()),
     CurSILFn(f) {
   // Apply sanitizer attributes to the function.
@@ -2470,6 +2477,47 @@
   }
 }
 
+void IRGenSILFunction::visitUnwindInst(swift::UnwindInst *i) {
+  IGM.unimplemented(i->getLoc().getSourceLoc(),
+                    "unwind instruction");
+  Builder.CreateUnreachable();
+  Builder.emitBlock(createBasicBlock("unwind"));
+}
+
+void IRGenSILFunction::visitYieldInst(swift::YieldInst *i) {
+  IGM.unimplemented(i->getLoc().getSourceLoc(),
+                    "yield instruction");
+  Builder.CreateUnreachable();
+  Builder.emitBlock(createBasicBlock("yield"));
+}
+
+void IRGenSILFunction::visitBeginApplyInst(BeginApplyInst *i) {
+  IGM.unimplemented(i->getLoc().getSourceLoc(),
+                    "begin_apply instruction");
+
+  // Set undef lowered values for all the results.
+  for (auto result : i->getYieldedValues()) {
+    auto &resultTI = getTypeInfo(result->getType());
+    if (result->getType().isAddress()) {
+      setLoweredAddress(result, resultTI.getUndefAddress());
+    } else {
+      Explosion undef;
+      emitFakeExplosion(resultTI, undef);
+      setLoweredExplosion(result, undef);
+    }
+  }
+}
+
+void IRGenSILFunction::visitEndApplyInst(EndApplyInst *i) {
+  IGM.unimplemented(i->getLoc().getSourceLoc(),
+                    "end_apply instruction");
+}
+
+void IRGenSILFunction::visitAbortApplyInst(AbortApplyInst *i) {
+  IGM.unimplemented(i->getLoc().getSourceLoc(),
+                    "abort_apply instruction");
+}
+
 static llvm::BasicBlock *emitBBMapForSwitchValue(
         IRGenSILFunction &IGF,
         SmallVectorImpl<std::pair<SILValue, llvm::BasicBlock*>> &dests,
@@ -5060,7 +5108,7 @@
   Builder.CreateCondBr(cond, failBB, contBB);
   Builder.emitBlock(failBB);
 
-  if (IGM.IRGen.Opts.Optimize) {
+  if (IGM.IRGen.Opts.shouldOptimize()) {
     // Emit unique side-effecting inline asm calls in order to eliminate
     // the possibility that an LLVM optimization or code generation pass
     // will merge these blocks back together again. We emit an empty asm
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 31069ff..80c2e9b 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -73,47 +73,60 @@
   return true;
 }
 
-static bool modResultType(GenericEnvironment *genEnv,
-                          CanSILFunctionType loweredTy,
-                          irgen::IRGenModule &Mod);
+static bool shouldTransformResults(GenericEnvironment *env,
+                                   CanSILFunctionType fnType,
+                                   irgen::IRGenModule &IGM);
 
-static bool containsLargeLoadable(GenericEnvironment *GenericEnv,
-                                  ArrayRef<SILParameterInfo> params,
-                                  irgen::IRGenModule &Mod) {
-  for (SILParameterInfo param : params) {
-    SILType storageType = param.getSILStorageType();
-    CanType currCanType = storageType.getSwiftRValueType();
-    if (SILFunctionType *currSILFunctionType =
-            dyn_cast<SILFunctionType>(currCanType.getPointer())) {
-      if (containsLargeLoadable(GenericEnv,
-                                currSILFunctionType->getParameters(), Mod) ||
-          modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
-                        Mod)) {
-        return true;
-      }
-    } else {
-      switch (param.getConvention()) {
-      case ParameterConvention::Indirect_In_Guaranteed:
-      case ParameterConvention::Indirect_Inout:
-      case ParameterConvention::Indirect_InoutAliasable:
-      case ParameterConvention::Indirect_In: {
-        continue;
-      }
-      default:
-        break;
-      }
-      if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
-        return true;
-      }
-    }
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+                                        CanSILFunctionType fnType,
+                                        irgen::IRGenModule &IGM);
+
+static bool shouldTransformParameter(GenericEnvironment *env,
+                                     SILParameterInfo param,
+                                     irgen::IRGenModule &IGM) {
+  SILType storageType = param.getSILStorageType();
+
+  // FIXME: only function types and not recursively-transformable types?
+  if (auto fnType = storageType.getAs<SILFunctionType>())
+    return shouldTransformFunctionType(env, fnType, IGM);
+
+  switch (param.getConvention()) {
+  case ParameterConvention::Indirect_In_Guaranteed:
+  case ParameterConvention::Indirect_Inout:
+  case ParameterConvention::Indirect_InoutAliasable:
+  case ParameterConvention::Indirect_In:
+    return false;
+  default:
+    return isLargeLoadableType(env, storageType, IGM);
   }
+}
+
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+                                        CanSILFunctionType fnType,
+                                        irgen::IRGenModule &IGM) {
+  if (shouldTransformResults(env, fnType, IGM))
+    return true;
+
+  for (auto param : fnType->getParameters()) {
+    if (shouldTransformParameter(env, param, IGM))
+      return true;
+  }
+
+  for (auto yield : fnType->getYields()) {
+    if (shouldTransformParameter(env, yield, IGM))
+      return true;
+  }
+
   return false;
 }
 
 // Forward declarations - functions depend on each other
 static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
-             SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod);
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+                 irgen::IRGenModule &IGM);
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+             irgen::IRGenModule &IGM);
 static SILType getNewSILType(GenericEnvironment *GenericEnv,
                              SILType storageType, irgen::IRGenModule &Mod);
 
@@ -135,11 +148,11 @@
 
 static SmallVector<SILResultInfo, 2>
 getNewResults(GenericEnvironment *GenericEnv,
-              SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
+              CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
   // Get new SIL Function results - same as old results UNLESS:
   // 1) Function type results might have a different signature
   // 2) Large loadables are replaced by @out version
-  auto origResults = currSILFunctionType->getResults();
+  auto origResults = fnType->getResults();
   SmallVector<SILResultInfo, 2> newResults;
   for (auto result : origResults) {
     SILType currResultTy = result.getSILStorageType();
@@ -152,8 +165,7 @@
                               result.getConvention());
       newResults.push_back(newResult);
     } else if ((newSILType != currResultTy) &&
-               modResultType(GenericEnv,
-                             CanSILFunctionType(currSILFunctionType), Mod)) {
+               shouldTransformResults(GenericEnv, fnType, Mod)) {
       // Case (2) Above
       SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
                                      ResultConvention::Indirect);
@@ -165,39 +177,28 @@
   return newResults;
 }
 
-static SILFunctionType *
-getNewSILFunctionTypePtr(GenericEnvironment *GenericEnv,
-                         SILFunctionType *currSILFunctionType,
-                         irgen::IRGenModule &Mod) {
-  if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
-    return currSILFunctionType;
+static CanSILFunctionType
+getNewSILFunctionType(GenericEnvironment *env,
+                      CanSILFunctionType fnType,
+                      irgen::IRGenModule &IGM) {
+  if (!modifiableFunction(fnType)) {
+    return fnType;
   }
-  SmallVector<SILParameterInfo, 4> newArgTys =
-      getNewArgTys(GenericEnv, currSILFunctionType, Mod);
-  SILFunctionType *newSILFunctionType = SILFunctionType::get(
-      currSILFunctionType->getGenericSignature(),
-      currSILFunctionType->getExtInfo(),
-      currSILFunctionType->getCalleeConvention(), newArgTys,
-      getNewResults(GenericEnv, currSILFunctionType, Mod),
-      currSILFunctionType->getOptionalErrorResult(),
-      currSILFunctionType->getASTContext(),
-      currSILFunctionType->getWitnessMethodConformanceOrNone());
-  return newSILFunctionType;
-}
-
-static SILType getNewSILFunctionType(GenericEnvironment *GenericEnv,
-                                     SILFunctionType *currSILFunctionType,
-                                     irgen::IRGenModule &Mod) {
-  if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
-    SILType newSILType = SILType::getPrimitiveObjectType(
-        currSILFunctionType->getCanonicalType());
-    return newSILType;
-  }
-  SILFunctionType *newSILFunctionType =
-      getNewSILFunctionTypePtr(GenericEnv, currSILFunctionType, Mod);
-  SILType newSILType =
-      SILType::getPrimitiveObjectType(newSILFunctionType->getCanonicalType());
-  return newSILType;
+  auto newParams = getNewParameters(env, fnType, IGM);
+  auto newYields = getNewYields(env, fnType, IGM);
+  auto newResults = getNewResults(env, fnType, IGM);
+  auto newFnType = SILFunctionType::get(
+      fnType->getGenericSignature(),
+      fnType->getExtInfo(),
+      fnType->getCoroutineKind(),
+      fnType->getCalleeConvention(),
+      newParams,
+      newYields,
+      newResults,
+      fnType->getOptionalErrorResult(),
+      fnType->getASTContext(),
+      fnType->getWitnessMethodConformanceOrNone());
+  return newFnType;
 }
 
 // Get the function type or the optional function type
@@ -223,35 +224,22 @@
                                           SILType storageType,
                                           irgen::IRGenModule &Mod) {
   SILType newSILType = storageType;
-  CanType currCanType = storageType.getSwiftRValueType();
-  OptionalTypeKind optKind;
-  if (auto optionalType = currCanType.getAnyOptionalObjectType(optKind)) {
-    assert(optKind != OptionalTypeKind::OTK_None &&
-           "Expected Real Optional Type");
-    if (auto *currSILFunctionType =
-            dyn_cast<SILFunctionType>(optionalType.getPointer())) {
-      if (containsLargeLoadable(GenericEnv,
-                                currSILFunctionType->getParameters(), Mod) ||
-          modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
-                        Mod)) {
+  if (auto objectType = storageType.getAnyOptionalObjectType()) {
+    if (auto fnType = objectType.getAs<SILFunctionType>()) {
+      if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+        auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);        
         newSILType =
-            getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
-        currCanType = newSILType.getSwiftRValueType();
-        auto newType = OptionalType::get(optKind, currCanType);
-        CanType newCanType = newType->getCanonicalType();
-        newSILType = SILType::getPrimitiveObjectType(newCanType);
-        if (storageType.isAddress()) {
-          newSILType = newSILType.getAddressType();
-        }
+          SILType::getPrimitiveType(newFnType, storageType.getCategory());
+        newSILType = SILType::getOptionalType(newSILType);
       }
     }
   }
   return newSILType;
 }
 
-static bool modResultType(GenericEnvironment *genEnv,
-                          CanSILFunctionType loweredTy,
-                          irgen::IRGenModule &Mod) {
+static bool shouldTransformResults(GenericEnvironment *genEnv,
+                                   CanSILFunctionType loweredTy,
+                                   irgen::IRGenModule &Mod) {
   if (!modifiableFunction(loweredTy)) {
     return false;
   }
@@ -274,53 +262,55 @@
     genEnv = getGenericEnvironment(F->getModule(), loweredTy);
   }
 
-  return modResultType(genEnv, loweredTy, Mod);
+  return shouldTransformResults(genEnv, loweredTy, Mod);
+}
+
+static SILParameterInfo
+getNewParameter(GenericEnvironment *env, SILParameterInfo param,
+                irgen::IRGenModule &IGM) {
+  SILType storageType = param.getSILStorageType();
+  SILType newOptFuncType =
+      getNewOptionalFunctionType(env, storageType, IGM);
+  if (newOptFuncType != storageType) {
+    return param.getWithType(newOptFuncType.getSwiftRValueType());
+  }
+
+  if (auto paramFnType = storageType.getAs<SILFunctionType>()) {
+    if (shouldTransformFunctionType(env, paramFnType, IGM)) {
+      auto newFnType = getNewSILFunctionType(env, paramFnType, IGM);
+      return param.getWithType(newFnType);
+    } else {
+      return param;
+    }
+  } else if (isLargeLoadableType(env, storageType, IGM)) {
+    return  SILParameterInfo(storageType.getSwiftRValueType(),
+                             ParameterConvention::Indirect_In_Constant);
+  } else {
+    return param;
+  }
 }
 
 static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
-             SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
-  ArrayRef<SILParameterInfo> params = currSILFunctionType->getParameters();
-  SmallVector<SILParameterInfo, 4> newArgTys;
-  for (SILParameterInfo param : params) {
-    SILType storageType = param.getSILStorageType();
-    SILType newOptFuncType =
-        getNewOptionalFunctionType(GenericEnv, storageType, Mod);
-    if (newOptFuncType != storageType) {
-      auto newParam = SILParameterInfo(newOptFuncType.getSwiftRValueType(),
-                                       param.getConvention());
-      newArgTys.push_back(newParam);
-      continue;
-    }
-    CanType currCanType = storageType.getSwiftRValueType();
-    if (SILFunctionType *currSILFunctionType =
-            dyn_cast<SILFunctionType>(currCanType.getPointer())) {
-      if (containsLargeLoadable(GenericEnv,
-                                currSILFunctionType->getParameters(), Mod) ||
-          modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
-                        Mod)) {
-        SILType newSILType =
-            getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
-        if (storageType.isAddress()) {
-          newSILType = newSILType.getAddressType();
-        }
-        auto newParam = SILParameterInfo(newSILType.getSwiftRValueType(),
-                                         param.getConvention());
-        newArgTys.push_back(newParam);
-      } else {
-        newArgTys.push_back(param);
-      }
-    } else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
-      SILType addrType = storageType.getAddressType();
-      auto newParam =
-          SILParameterInfo(addrType.getSwiftRValueType(),
-                           ParameterConvention::Indirect_In_Constant);
-      newArgTys.push_back(newParam);
-    } else {
-      newArgTys.push_back(param);
-    }
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+                 irgen::IRGenModule &IGM) {
+  SmallVector<SILParameterInfo, 4> newParams;
+  for (SILParameterInfo param : fnType->getParameters()) {
+    auto newParam = getNewParameter(env, param, IGM);
+    newParams.push_back(newParam);
   }
-  return newArgTys;
+  return newParams;
+}
+
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+             irgen::IRGenModule &IGM) {
+  SmallVector<SILYieldInfo, 2> newYields;
+  for (auto oldYield : fnType->getYields()) {
+    auto newYieldAsParam = getNewParameter(env, oldYield, IGM);
+    newYields.push_back(SILYieldInfo(newYieldAsParam.getType(),
+                                     newYieldAsParam.getConvention()));
+  }
+  return newYields;
 }
 
 static SILType getNewSILType(GenericEnvironment *GenericEnv,
@@ -329,17 +319,11 @@
   if (newSILType != storageType) {
     return newSILType;
   }
-  CanType currCanType = storageType.getSwiftRValueType();
-  if (SILFunctionType *currSILFunctionType =
-          dyn_cast<SILFunctionType>(currCanType.getPointer())) {
-    if (containsLargeLoadable(GenericEnv, currSILFunctionType->getParameters(),
-                              Mod) ||
-        modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
-                      Mod)) {
-      newSILType = getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
-      if (storageType.isAddress()) {
-        newSILType = newSILType.getAddressType();
-      }
+  if (auto fnType = storageType.getAs<SILFunctionType>()) {
+    if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+      auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);
+      newSILType = SILType::getPrimitiveType(newFnType,
+                                             storageType.getCategory());
     }
   } else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
     newSILType = storageType.getAddressType();
@@ -584,14 +568,14 @@
     return;
   }
   // Check callee - need new generic env:
-  SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+  CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
   GenericEnvironment *genEnvCallee = nullptr;
   if (origSILFunctionType->isPolymorphic()) {
     genEnvCallee = getGenericEnvironment(
         applySite.getModule(), CanSILFunctionType(origSILFunctionType));
   }
-  SILFunctionType *newSILFunctionType =
-      getNewSILFunctionTypePtr(genEnvCallee, origSILFunctionType, pass.Mod);
+  auto newSILFunctionType =
+      getNewSILFunctionType(genEnvCallee, origSILFunctionType, pass.Mod);
   if (origSILFunctionType != newSILFunctionType) {
     pass.applies.push_back(applySite.getInstruction());
   }
@@ -617,27 +601,19 @@
     return;
   }
   SILType currSILType = instr->getType();
-  CanType currCanType = currSILType.getSwiftRValueType();
-  SILFunctionType *currSILFunctionType =
-      dyn_cast<SILFunctionType>(currCanType.getPointer());
-  if (!currSILFunctionType) {
-    llvm_unreachable("unsupported type");
-  }
+  auto fnType = currSILType.castTo<SILFunctionType>();
+
   GenericEnvironment *genEnv = nullptr;
-  if (currSILFunctionType->isPolymorphic()) {
-    genEnv = getGenericEnvironment(instr->getModule(),
-                                   CanSILFunctionType(currSILFunctionType));
+  if (fnType->isPolymorphic()) {
+    genEnv = getGenericEnvironment(instr->getModule(), fnType);
   }
   Lowering::GenericContextScope GenericScope(
-      instr->getModule().Types, currSILFunctionType->getGenericSignature());
-  if (containsLargeLoadable(genEnv, currSILFunctionType->getParameters(),
-                            pass.Mod) ||
-      modResultType(genEnv, CanSILFunctionType(currSILFunctionType),
-                    pass.Mod)) {
+      instr->getModule().Types, fnType->getGenericSignature());
+  if (shouldTransformFunctionType(genEnv, fnType, pass.Mod)) {
     pass.methodInstsToMod.push_back(instr);
     return;
   }
-  if (newResultsDiffer(genEnv, currSILFunctionType->getResults(), pass.Mod)) {
+  if (newResultsDiffer(genEnv, fnType->getResults(), pass.Mod)) {
     pass.methodInstsToMod.push_back(instr);
   }
 }
@@ -763,8 +739,8 @@
     if (!genEnv && canFuncType->isPolymorphic()) {
       genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
     }
-    SILFunctionType *newSILFunctionType =
-        getNewSILFunctionTypePtr(genEnv, funcType, pass.Mod);
+    auto newSILFunctionType =
+        getNewSILFunctionType(genEnv, funcType, pass.Mod);
     if (funcType != newSILFunctionType) {
       pass.tupleInstsToMod.push_back(instr);
     }
@@ -1255,23 +1231,22 @@
       if (!modifiableApply(applySite, pass.Mod)) {
         continue;
       }
-      SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
-      auto canSILFunctionType = CanSILFunctionType(origSILFunctionType);
+      CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
       Lowering::GenericContextScope GenericScope(
-          silModue.Types, canSILFunctionType->getGenericSignature());
+          silModue.Types, origSILFunctionType->getGenericSignature());
       GenericEnvironment *genEnv = nullptr;
       if (origSILFunctionType->isPolymorphic()) {
-        genEnv = getGenericEnvironment(silModue, canSILFunctionType);
+        genEnv = getGenericEnvironment(silModue, origSILFunctionType);
       }
-      if (!modResultType(genEnv, canSILFunctionType, pass.Mod)) {
+      if (!shouldTransformResults(genEnv, origSILFunctionType, pass.Mod)) {
         continue;
       }
-      auto singleResult = canSILFunctionType->getSingleResult();
+      auto singleResult = origSILFunctionType->getSingleResult();
       auto resultStorageType = singleResult.getSILStorageType();
       if (!isLargeLoadableType(genEnv, resultStorageType, pass.Mod)) {
         // Make sure it is a function type
         auto canType = resultStorageType.getSwiftRValueType();
-        if (!dyn_cast<SILFunctionType>(canType.getPointer())) {
+        if (!isa<SILFunctionType>(canType)) {
           // Check if it is an optional funciton type
           OptionalTypeKind optKind;
           auto optionalType = canType.getAnyOptionalObjectType(optKind);
@@ -1607,19 +1582,16 @@
 }
 
 static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
-  SILType currSILType = instr->getType().getObjectType();
-  CanType currCanType = currSILType.getSwiftRValueType();
-  SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
-  assert(funcType && "Expected SILFunctionType as tuple's return");
-  CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
+  SILType currSILType = instr->getType();
+  auto funcType = currSILType.castTo<SILFunctionType>();
   GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
-  if (!genEnv && canFuncType->isPolymorphic()) {
-    genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
+  if (!genEnv && funcType->isPolymorphic()) {
+    genEnv = getGenericEnvironment(instr->getModule(), funcType);
   }
-  SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
-  if (currSILType.isAddress()) {
-    newSILType = newSILType.getAddressType();
-  }
+  auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+  SILType newSILType =
+    SILType::getPrimitiveType(newFnType, currSILType.getCategory());
+
   auto II = instr->getIterator();
   ++II;
   SILBuilder castBuilder(II);
@@ -1993,16 +1965,14 @@
 
   for (MethodInst *instr : pass.methodInstsToMod) {
     SILType currSILType = instr->getType();
-    CanType currCanType = currSILType.getSwiftRValueType();
-    SILFunctionType *currSILFunctionType =
-        dyn_cast<SILFunctionType>(currCanType.getPointer());
+    auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
     GenericEnvironment *genEnvForMethod = nullptr;
     if (currSILFunctionType->isPolymorphic()) {
       genEnvForMethod = getGenericEnvironment(
           instr->getModule(), CanSILFunctionType(currSILFunctionType));
     }
-    SILType newSILType =
-        getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod);
+    SILType newSILType = SILType::getPrimitiveObjectType(
+        getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod));
     auto member = instr->getMember();
     auto loc = instr->getLoc();
     SILBuilder methodBuilder(instr);
@@ -2104,7 +2074,9 @@
                                    origResultInfo.getConvention());
     auto NewTy = SILFunctionType::get(
         loweredTy->getGenericSignature(), loweredTy->getExtInfo(),
+        loweredTy->getCoroutineKind(),
         loweredTy->getCalleeConvention(), loweredTy->getParameters(),
+        loweredTy->getYields(),
         newSILResultInfo, loweredTy->getOptionalErrorResult(),
         F->getModule().getASTContext(),
         loweredTy->getWitnessMethodConformanceOrNone());
@@ -2131,10 +2103,8 @@
     if (!genEnv && loweredTy->isPolymorphic()) {
       genEnv = getGenericEnvironment(F->getModule(), loweredTy);
     }
-    if (containsLargeLoadable(
-            genEnv, F->getLoweredFunctionType()->getParameters(), *currIRMod) ||
-        modResultType(genEnv, CanSILFunctionType(F->getLoweredFunctionType()),
-                      *currIRMod)) {
+    if (shouldTransformFunctionType(genEnv, F->getLoweredFunctionType(),
+                                    *currIRMod)) {
       modFuncs.insert(F);
     }
     return;
@@ -2178,16 +2148,15 @@
 getOperandTypeWithCastIfNecessary(SILInstruction *containingInstr, SILValue op,
                                   IRGenModule &Mod, SILBuilder &builder) {
   SILType currSILType = op->getType();
-  CanType currCanType = currSILType.getSwiftRValueType();
-  SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
-  if (funcType) {
+  if (auto funcType = currSILType.getAs<SILFunctionType>()) {
     CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
     GenericEnvironment *genEnv =
         containingInstr->getFunction()->getGenericEnvironment();
     if (!genEnv && canFuncType->isPolymorphic()) {
       genEnv = getGenericEnvironment(containingInstr->getModule(), canFuncType);
     }
-    SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
+    auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+    SILType newSILType = SILType::getPrimitiveObjectType(newFnType);
     if (currSILType.isAddress()) {
       newSILType = newSILType.getAddressType(); // we need address for loads
       if (newSILType != currSILType) {
@@ -2242,7 +2211,7 @@
       callee = applySite.getCallee();
     }
   }
-  SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+  CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
   auto origCanType = CanSILFunctionType(origSILFunctionType);
   Lowering::GenericContextScope GenericScope(
       getModule()->Types, origCanType->getGenericSignature());
@@ -2251,8 +2220,8 @@
     genEnv = getGenericEnvironment(applyInst->getModule(),
                                    CanSILFunctionType(origSILFunctionType));
   }
-  SILFunctionType *newSILFunctionType =
-      getNewSILFunctionTypePtr(genEnv, origSILFunctionType, *currIRMod);
+  CanSILFunctionType newSILFunctionType =
+      getNewSILFunctionType(genEnv, origSILFunctionType, *currIRMod);
   CanSILFunctionType newCanSILFuncType(newSILFunctionType);
   SILFunctionConventions newSILFunctionConventions(newCanSILFuncType,
                                                    *getModule());
@@ -2432,23 +2401,19 @@
     if (auto *thinToPointer = dyn_cast<ThinFunctionToPointerInst>(convInstr)) {
       currSILType = thinToPointer->getOperand()->getType();
     }
-    CanType currCanType = currSILType.getSwiftRValueType();
-    SILFunctionType *currSILFunctionType =
-        dyn_cast<SILFunctionType>(currCanType.getPointer());
+    auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
     Lowering::GenericContextScope GenericScope(
         getModule()->Types,
-        CanSILFunctionType(currSILFunctionType)->getGenericSignature());
-    if (!currSILFunctionType) {
-      llvm_unreachable("unsupported type");
-    }
+        currSILFunctionType->getGenericSignature());
     GenericEnvironment *genEnv =
         convInstr->getFunction()->getGenericEnvironment();
     auto loweredTy = convInstr->getFunction()->getLoweredFunctionType();
     if (!genEnv && loweredTy->isPolymorphic()) {
       genEnv = getGenericEnvironment(convInstr->getModule(), loweredTy);
     }
-    SILType newType =
+    CanSILFunctionType newFnType =
         getNewSILFunctionType(genEnv, currSILFunctionType, *currIRMod);
+    SILType newType = SILType::getPrimitiveObjectType(newFnType);
     SILBuilder convBuilder(convInstr);
     SingleValueInstruction *newInstr = nullptr;
     switch (convInstr->getKind()) {
@@ -2511,7 +2476,6 @@
 void LoadableByAddress::updateLoweredTypes(SILFunction *F) {
   IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
   CanSILFunctionType funcType = F->getLoweredFunctionType();
-  auto *currSILFunctionType = dyn_cast<SILFunctionType>(funcType.getPointer());
   Lowering::GenericContextScope GenericScope(getModule()->Types,
                                              funcType->getGenericSignature());
   GenericEnvironment *genEnv = F->getGenericEnvironment();
@@ -2519,10 +2483,8 @@
   if (!genEnv && loweredTy->isPolymorphic()) {
     genEnv = getGenericEnvironment(F->getModule(), loweredTy);
   }
-  auto *newFuncTy =
-      getNewSILFunctionTypePtr(genEnv, currSILFunctionType, *currIRMod);
-
-  F->rewriteLoweredTypeUnsafe(CanSILFunctionType(newFuncTy));
+  auto newFuncTy = getNewSILFunctionType(genEnv, funcType, *currIRMod);
+  F->rewriteLoweredTypeUnsafe(newFuncTy);
 }
 
 /// The entry point to this function transformation.
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index fe2fc05..7b3aa73 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -194,7 +194,7 @@
 
   // At -O0, create an alloca to keep the type alive.
   auto name = type->getFullName();
-  if (!IGF.IGM.IRGen.Opts.Optimize) {
+  if (!IGF.IGM.IRGen.Opts.shouldOptimize()) {
     auto temp = IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(),
                                  name);
     IGF.Builder.CreateStore(data, temp);
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 0dd1566..f72d034 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -57,7 +57,11 @@
 
       /// Type metadata at requirement index P of a generic nominal type.
       NominalTypeArgument,
-      LastWithPrimaryIndex = NominalTypeArgument,
+
+      /// Conditional conformance at index P (i.e. the P'th element) of a
+      /// conformance.
+      ConditionalConformance,
+      LastWithPrimaryIndex = ConditionalConformance,
 
       // Everything past this point has no index.
 
@@ -99,6 +103,7 @@
       case Kind::OutOfLineBaseProtocol:
       case Kind::NominalTypeArgumentConformance:
       case Kind::NominalTypeArgument:
+      case Kind::ConditionalConformance:
         return OperationCost::Load;
 
       case Kind::AssociatedConformance:
@@ -169,6 +174,10 @@
                              index.getValue()));
   }
 
+  void addConditionalConformanceComponent(unsigned index) {
+    Path.push_back(Component(Component::Kind::ConditionalConformance, index));
+  }
+
   /// Return an abstract measurement of the cost of this path.
   OperationCost cost() const {
     auto cost = OperationCost::Free;
diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp
index e27403f..003caf3 100644
--- a/lib/IRGen/StructLayout.cpp
+++ b/lib/IRGen/StructLayout.cpp
@@ -38,11 +38,6 @@
   llvm_unreachable("bad layout kind!");
 }
 
-/// Return the size of the standard heap header.
-Size irgen::getHeapHeaderSize(IRGenModule &IGM) {
-  return IGM.getPointerSize() + Size(8);
-}
-
 /// Perform structure layout on the given types.
 StructLayout::StructLayout(IRGenModule &IGM, CanType astTy,
                            LayoutKind layoutKind,
@@ -184,7 +179,7 @@
 
 void StructLayoutBuilder::addHeapHeader() {
   assert(StructFields.empty() && "adding heap header at a non-zero offset");
-  CurSize = getHeapHeaderSize(IGM);
+  CurSize = IGM.RefCountedStructSize;
   CurAlignment = IGM.getPointerAlignment();
   StructFields.push_back(IGM.RefCountedStructTy);
 }
diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h
index 70c1531..84128b8 100644
--- a/lib/IRGen/StructLayout.h
+++ b/lib/IRGen/StructLayout.h
@@ -395,8 +395,6 @@
                      const llvm::Twine &name = "") const;
 };
 
-Size getHeapHeaderSize(IRGenModule &IGM);
-
 /// Different policies for accessing a physical field.
 enum class FieldAccess : uint8_t {
   /// Instance variable offsets are constant.
diff --git a/lib/IRGen/WitnessIndex.h b/lib/IRGen/WitnessIndex.h
index fa11a7e..64d006e 100644
--- a/lib/IRGen/WitnessIndex.h
+++ b/lib/IRGen/WitnessIndex.h
@@ -25,15 +25,17 @@
 
 /// A class which encapsulates an index into a witness table.
 class WitnessIndex {
-  unsigned Value : 31;
+  // Negative values are indexing into the private area of a protocol witness
+  // table.
+  int Value : 31;
   unsigned IsPrefix : 1;
 public:
   WitnessIndex() = default;
-  WitnessIndex(ValueWitness index) : Value(unsigned(index)) {}
-  explicit WitnessIndex(unsigned index, bool isPrefix)
-    : Value(index), IsPrefix(isPrefix) {}
+  WitnessIndex(ValueWitness index) : Value(int(index)) {}
+  explicit WitnessIndex(int index, bool isPrefix)
+      : Value(index), IsPrefix(isPrefix) {}
 
-  unsigned getValue() const { return Value; }
+  int getValue() const { return Value; }
 
   bool isPrefix() const { return IsPrefix; }
 };
diff --git a/lib/Immediate/Immediate.cpp b/lib/Immediate/Immediate.cpp
index 967a64e..9d50334 100644
--- a/lib/Immediate/Immediate.cpp
+++ b/lib/Immediate/Immediate.cpp
@@ -195,12 +195,11 @@
                             /*, llvm::Linker::LinkerMode LinkerMode */)
 {
   llvm::LLVMContext &Ctx = SubModule->getContext();
-  auto OldHandler = Ctx.getDiagnosticHandler();
+  auto OldHandler = Ctx.getDiagnosticHandlerCallBack();
   void *OldDiagnosticContext = Ctx.getDiagnosticContext();
-  Ctx.setDiagnosticHandler(linkerDiagnosticHandler, nullptr);
+  Ctx.setDiagnosticHandlerCallBack(linkerDiagnosticHandler, nullptr);
   bool Failed = llvm::Linker::linkModules(*Module, std::move(SubModule));
-  Ctx.setDiagnosticHandler(OldHandler, OldDiagnosticContext);
-
+  Ctx.setDiagnosticHandlerCallBack(OldHandler, OldDiagnosticContext);
   return !Failed;
 }
 
diff --git a/lib/Immediate/REPL.cpp b/lib/Immediate/REPL.cpp
index 31cc858..f2f1329 100644
--- a/lib/Immediate/REPL.cpp
+++ b/lib/Immediate/REPL.cpp
@@ -966,7 +966,7 @@
     EE = builder.create();
 
     IRGenOpts.OutputFilenames.clear();
-    IRGenOpts.Optimize = false;
+    IRGenOpts.OptMode = OptimizationMode::NoOptimization;
     IRGenOpts.OutputKind = IRGenOutputKind::Module;
     IRGenOpts.UseJIT = true;
     IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::None;
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 29ea715..5c6bd6b 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -19,11 +19,11 @@
 #include "swift/AST/Expr.h"
 #include "swift/AST/Module.h"
 #include "swift/AST/ParameterList.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/AST/Types.h"
 #include "swift/AST/USRGeneration.h"
 #include "swift/Basic/SourceManager.h"
 #include "swift/Basic/StringExtras.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Markup/Markup.h"
 #include "swift/Sema/IDETypeChecking.h"
 #include "llvm/ADT/APInt.h"
@@ -352,9 +352,9 @@
 
     IndexSymbol Info;
     if (CtorTyRef)
-      if (!reportRef(CtorTyRef, Loc, Info))
+      if (!reportRef(CtorTyRef, Loc, Info, Data.AccKind))
         return false;
-    if (!reportRef(D, Loc, Info))
+    if (!reportRef(D, Loc, Info, Data.AccKind))
       return false;
 
     return true;
@@ -397,7 +397,8 @@
 
   bool report(ValueDecl *D);
   bool reportExtension(ExtensionDecl *D);
-  bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
+  bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
+                 Optional<AccessKind> AccKind);
 
   bool startEntity(Decl *D, IndexSymbol &Info);
   bool startEntityDecl(ValueDecl *D);
@@ -435,7 +436,7 @@
   bool initFuncDeclIndexSymbol(FuncDecl *D, IndexSymbol &Info);
   bool initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
   bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
-                              IndexSymbol &Info);
+                              IndexSymbol &Info, Optional<AccessKind> AccKind);
 
   bool indexComment(const Decl *D);
 
@@ -690,7 +691,7 @@
   // don't report this ref again when visitDeclReference reports it
   repressRefAtLoc(Loc);
 
-  if (!reportRef(D, Loc, Info)) {
+  if (!reportRef(D, Loc, Info, None)) {
     Cancelled = true;
     return false;
   }
@@ -716,7 +717,7 @@
     if (auto *VD = Comps.back()->getBoundDecl()) {
       if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
         IndexSymbol Info;
-        if (!reportRef(TAD, IdLoc, Info))
+        if (!reportRef(TAD, IdLoc, Info, None))
           return false;
         if (auto Ty = TAD->getUnderlyingTypeLoc().getType()) {
           NTD = Ty->getAnyNominal();
@@ -934,7 +935,8 @@
 }
 
 bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
-                                    IndexSymbol &Info) {
+                                    IndexSymbol &Info,
+                                    Optional<AccessKind> AccKind) {
   if (!shouldIndex(D, /*IsRef=*/true))
     return true; // keep walking
 
@@ -942,7 +944,7 @@
     if (initFuncRefIndexSymbol(D, Loc, Info))
       return true;
   } else if (isa<AbstractStorageDecl>(D)) {
-    if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info))
+    if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info, AccKind))
       return true;
   } else {
     if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
@@ -1146,7 +1148,9 @@
   return false;
 }
 
-bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc, IndexSymbol &Info) {
+bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D,
+                                                 SourceLoc Loc, IndexSymbol &Info,
+                                                 Optional<AccessKind> AccKind) {
 
   if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
     return true;
@@ -1154,7 +1158,7 @@
   if (!CurrentE)
     return false;
 
-  AccessKind Kind = CurrentE->hasLValueAccessKind() ? CurrentE->getLValueAccessKind() : AccessKind::Read;
+  AccessKind Kind = AccKind.hasValue() ? *AccKind : AccessKind::Read;
   switch (Kind) {
   case swift::AccessKind::Read:
     Info.roles |= (unsigned)SymbolRole::Read;
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 360cbe4..717c120 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -15,6 +15,7 @@
 #include "swift/AST/Module.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Migrator/ASTMigratorPass.h"
 #include "swift/Parse/Lexer.h"
 
diff --git a/lib/Migrator/TypeOfMigratorPass.cpp b/lib/Migrator/TypeOfMigratorPass.cpp
index b7cb259..3697b9c 100644
--- a/lib/Migrator/TypeOfMigratorPass.cpp
+++ b/lib/Migrator/TypeOfMigratorPass.cpp
@@ -16,6 +16,7 @@
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/Migrator/ASTMigratorPass.h"
 #include "swift/Parse/Lexer.h"
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cbc064f..5595983 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -613,7 +613,8 @@
     }
 
     if (Tok.isNot(tok::identifier)) {
-      diagnose(Loc, diag::inline_attribute_expect_option, AttrName);
+      diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+               "none");
       return false;
     }
 
@@ -623,7 +624,7 @@
     else if (Tok.getText() == "__always")
       kind = InlineKind::Always;
     else {
-      diagnose(Loc, diag::inline_attribute_unknown_option,
+      diagnose(Loc, diag::optimization_attribute_unknown_option,
                Tok.getText(), AttrName);
       return false;
     }
@@ -642,6 +643,46 @@
     break;
   }
 
+  case DAK_Optimize: {
+    if (!consumeIf(tok::l_paren)) {
+      diagnose(Loc, diag::attr_expected_lparen, AttrName,
+               DeclAttribute::isDeclModifier(DK));
+      return false;
+    }
+
+    if (Tok.isNot(tok::identifier)) {
+      diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+               "speed");
+      return false;
+    }
+
+    OptimizationMode optMode = OptimizationMode::NotSet;
+    if (Tok.getText() == "none")
+      optMode = OptimizationMode::NoOptimization;
+    else if (Tok.getText() == "speed")
+      optMode = OptimizationMode::ForSpeed;
+    else if (Tok.getText() == "size")
+      optMode = OptimizationMode::ForSize;
+    else {
+      diagnose(Loc, diag::optimization_attribute_unknown_option,
+               Tok.getText(), AttrName);
+      return false;
+    }
+    consumeToken(tok::identifier);
+    AttrRange = SourceRange(Loc, Tok.getRange().getStart());
+
+    if (!consumeIf(tok::r_paren)) {
+      diagnose(Loc, diag::attr_expected_rparen, AttrName,
+               DeclAttribute::isDeclModifier(DK));
+      return false;
+    }
+
+    if (!DiscardAttribute)
+      Attributes.add(new (Context) OptimizeAttr(AtLoc, AttrRange, optMode));
+
+    break;
+  }
+
   case DAK_Ownership: {
     // Handle weak/unowned/unowned(unsafe).
     Ownership Kind = AttrName == "weak" ? Ownership::Weak : Ownership::Unowned;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d3a64cc..46bfa7d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -165,9 +165,12 @@
 ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
                                              bool isExprBasic,
                                              bool isForConditionalDirective) {
+  SyntaxParsingContextChild ExprSequnceContext(SyntaxContext,
+                                               SyntaxContextKind::Expr);
   SmallVector<Expr*, 8> SequencedExprs;
   SourceLoc startLoc = Tok.getLoc();
   bool HasCodeCompletion = false;
+  bool PendingTernary = false;
 
   while (true) {
     if (isForConditionalDirective && Tok.isAtStartOfLine())
@@ -189,6 +192,12 @@
     }
     SequencedExprs.push_back(Primary.get());
 
+    // We know we can make a syntax node for ternary expression.
+    if (PendingTernary) {
+      SyntaxContext->makeNode(SyntaxKind::TernaryExpr, Tok.getLoc());
+      PendingTernary = false;
+    }
+
     if (isForConditionalDirective && Tok.isAtStartOfLine())
       break;
     
@@ -245,6 +254,10 @@
                                colonLoc);
       SequencedExprs.push_back(unresolvedIf);
       Message = diag::expected_expr_after_if_colon;
+
+      // Wait for the next expression to make a syntax node for ternary
+      // expression.
+      PendingTernary = true;
       break;
     }
         
@@ -368,6 +381,8 @@
 /// sequence, but this isn't enforced until sequence-folding.
 ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
                                                     bool isExprBasic) {
+  SyntaxParsingContextChild ElementContext(SyntaxContext,
+                                           SyntaxContextKind::Expr);
   SourceLoc tryLoc;
   bool hadTry = consumeIf(tok::kw_try, tryLoc);
   Optional<Token> trySuffix;
@@ -473,7 +488,6 @@
     Tok.setKind(tok::oper_prefix);
     LLVM_FALLTHROUGH;
   case tok::oper_prefix:
-    SyntaxContext->addTokenSyntax(Tok.getLoc());
     Operator = parseExprOperator();
     break;
   case tok::oper_binary_spaced:
@@ -867,7 +881,8 @@
                                         lSquareLoc, indexArgs, indexArgLabels,
                                         indexArgLabelLocs,
                                         rSquareLoc,
-                                        trailingClosure);
+                                        trailingClosure,
+                                        SyntaxKind::Unknown);
     if (status.hasCodeCompletion())
       return makeParserCodeCompletionResult<Expr>();
     if (status.isError())
@@ -1216,7 +1231,8 @@
       ParserStatus status = parseExprList(
           tok::l_square, tok::r_square,
           /*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
-          indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure);
+          indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure,
+          SyntaxKind::Unknown);
       if (status.hasCodeCompletion())
         return makeParserCodeCompletionResult<Expr>();
       if (status.isError() || Result.isNull())
@@ -1389,8 +1405,7 @@
   case tok::integer_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::integer_literal);
-    SyntaxContext->addTokenSyntax(Loc);
-    SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr);
+    SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Tok.getLoc());
     Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1398,8 +1413,7 @@
   case tok::floating_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::floating_literal);
-    SyntaxContext->addTokenSyntax(Loc);
-    SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr);
+    SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Tok.getLoc());
     Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1420,13 +1434,17 @@
     Result = parseExprStringLiteral();
     break;
   
-  case tok::kw_nil:
+  case tok::kw_nil: {
+    SyntaxParsingContextChild NilContext(SyntaxContext, SyntaxKind::NilLiteralExpr);
     Result = makeParserResult(
                       new (Context) NilLiteralExpr(consumeToken(tok::kw_nil)));
     break;
+  }
 
   case tok::kw_true:
   case tok::kw_false: {
+    SyntaxParsingContextChild BoolContext(SyntaxContext,
+                                          SyntaxKind::BooleanLiteralExpr);
     bool isTrue = Tok.is(tok::kw_true);
     Result = makeParserResult(
                new (Context) BooleanLiteralExpr(isTrue, consumeToken()));
@@ -1519,10 +1537,13 @@
     break;
 
     // If the next token is '_', parse a discard expression.
-  case tok::kw__:
+  case tok::kw__: {
+    SyntaxParsingContextChild DAContext(SyntaxContext,
+                                        SyntaxKind::DiscardAssignmentExpr);
     Result = makeParserResult(
       new (Context) DiscardAssignmentExpr(consumeToken(), /*Implicit=*/false));
     break;
+  }
 
   case tok::pound_selector: // expr-selector
     Result = parseExprSelector();
@@ -1608,7 +1629,8 @@
                                           lParenLoc, args, argLabels,
                                           argLabelLocs,
                                           rParenLoc,
-                                          trailingClosure);
+                                          trailingClosure,
+                                          SyntaxKind::FunctionCallArgumentList);
       if (status.isError())
         return nullptr;
 
@@ -1657,7 +1679,8 @@
   }
 
   case tok::l_paren:
-    Result = parseExprList(tok::l_paren, tok::r_paren);
+    Result = parseExprList(tok::l_paren, tok::r_paren,
+                           SyntaxKind::FunctionCallArgumentList);
     break;
 
   case tok::l_square:
@@ -1805,13 +1828,10 @@
   Token EntireTok = Tok;
 
   // Create a syntax node for string literal.
-  SyntaxContext->addTokenSyntax(Tok.getLoc());
-  SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr);
-  SyntaxParsingContextChild LocalContext(SyntaxContext,
-                                         SyntaxContextKind::Expr);
+  SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, peekToken().getLoc());
 
   // FIXME: Avoid creating syntax nodes for string interpolation.
-  LocalContext.disable();
+  SyntaxParsingContextChild LocalContext(SyntaxContext, /*disabled*/true);
 
   // The start location of the entire string literal.
   SourceLoc Loc = Tok.getLoc();
@@ -1883,7 +1903,8 @@
       assert(Tok.is(tok::l_paren));
       TokReceiver->registerTokenKindChange(Tok.getLoc(),
                                            tok::string_interpolation_anchor);
-      ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren);
+      ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren,
+                                           SyntaxKind::Unknown);
       Status |= E;
       if (E.isNonNull()) {
         Exprs.push_back(E.get());
@@ -1995,6 +2016,10 @@
   SourceLoc lparenLoc = consumeToken(tok::l_paren);
   SourceLoc rparenLoc;
   while (true) {
+    // The following code may backtrack; so we disable the syntax tree creation
+    // in this scope.
+    SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
+
     // Terminate at ')'.
     if (Tok.is(tok::r_paren)) {
       rparenLoc = consumeToken(tok::r_paren);
@@ -2054,6 +2079,8 @@
 ///     unqualified-decl-name generic-args?
 Expr *Parser::parseExprIdentifier() {
   assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
+  SyntaxParsingContextChild IDSyntaxContext(SyntaxContext,
+                                            SyntaxKind::IdentifierExpr);
   Token IdentTok = Tok;
 
   // Parse the unqualified-decl-name.
@@ -2143,6 +2170,7 @@
 
 Expr *Parser::parseExprEditorPlaceholder(Token PlaceholderTok,
                                          Identifier PlaceholderId) {
+  SyntaxParsingContextChild DisableContext(SyntaxContext, /*disabled*/true);
   assert(PlaceholderTok.is(tok::identifier));
   assert(PlaceholderId.isEditorPlaceholder());
 
@@ -2752,7 +2780,8 @@
 ///   expr-paren-element:
 ///     (identifier ':')? expr
 ///
-ParserResult<Expr> Parser::parseExprList(tok leftTok, tok rightTok) {
+ParserResult<Expr>
+Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
   SmallVector<Expr*, 8> subExprs;
   SmallVector<Identifier, 8> subExprNames;
   SmallVector<SourceLoc, 8> subExprNameLocs;
@@ -2766,7 +2795,8 @@
                                       subExprNames,
                                       subExprNameLocs,
                                       rightLoc,
-                                      trailingClosure);
+                                      trailingClosure,
+                                      Kind);
 
   // A tuple with a single, unlabeled element is just parentheses.
   if (subExprs.size() == 1 &&
@@ -2801,7 +2831,8 @@
                                    SmallVectorImpl<Identifier> &exprLabels,
                                    SmallVectorImpl<SourceLoc> &exprLabelLocs,
                                    SourceLoc &rightLoc,
-                                   Expr *&trailingClosure) {
+                                   Expr *&trailingClosure,
+                                   SyntaxKind Kind) {
   trailingClosure = nullptr;
 
   StructureMarkerRAII ParsingExprList(*this, Tok);
@@ -2812,6 +2843,7 @@
                                   rightTok == tok::r_paren
                                     ? diag::expected_rparen_expr_list
                                     : diag::expected_rsquare_expr_list,
+                                  Kind,
                                   [&] () -> ParserStatus {
     Identifier FieldName;
     SourceLoc FieldNameLoc;
@@ -2823,6 +2855,8 @@
     ParserStatus Status;
     Expr *SubExpr = nullptr;
     if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
+      SyntaxParsingContextChild operatorContext(SyntaxContext,
+                                                SyntaxContextKind::Expr);
       SourceLoc Loc;
       Identifier OperName;
       if (parseAnyIdentifier(OperName, Loc, diag::expected_operator_ref)) {
@@ -2963,7 +2997,8 @@
                                       lParenLoc, args, argLabels,
                                       argLabelLocs,
                                       rParenLoc,
-                                      trailingClosure);
+                                      trailingClosure,
+                                      SyntaxKind::FunctionCallArgumentList);
   if (status.hasCodeCompletion())
     return makeParserCodeCompletionResult<Expr>();
   if (status.isError())
@@ -3055,7 +3090,8 @@
                                       lParenLoc, args, argLabels,
                                       argLabelLocs,
                                       rParenLoc,
-                                      trailingClosure);
+                                      trailingClosure,
+                                      SyntaxKind::FunctionCallArgumentList);
 
   // Form the call.
   auto Result = makeParserResult(status | fn, 
@@ -3081,6 +3117,8 @@
 ///     expr-dictionary
 //      lsquare-starting ']'
 ParserResult<Expr> Parser::parseExprCollection(SourceLoc LSquareLoc) {
+  SyntaxParsingContextChild ArrayOrDictContext(SyntaxContext);
+
   // If the caller didn't already consume the '[', do so now.
   if (LSquareLoc.isInvalid())
     LSquareLoc = consumeToken(tok::l_square);
@@ -3091,6 +3129,8 @@
 
   // [] is always an array.
   if (Tok.is(tok::r_square)) {
+    // FIXME: Handle empty array syntax node.
+    ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
     SourceLoc RSquareLoc = consumeToken(tok::r_square);
     return makeParserResult(
                     ArrayExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
@@ -3098,29 +3138,43 @@
 
   // [:] is always an empty dictionary.
   if (Tok.is(tok::colon) && peekToken().is(tok::r_square)) {
+    // FIXME: Handle empty dictionary syntax node.
+    ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
     consumeToken(tok::colon);
     SourceLoc RSquareLoc = consumeToken(tok::r_square);
     return makeParserResult(
                   DictionaryExpr::create(Context, LSquareLoc, {}, RSquareLoc));
   }
 
-  // Parse the first expression.
-  ParserResult<Expr> FirstExpr
-    = parseExpr(diag::expected_expr_in_collection_literal);
-  if (FirstExpr.isNull()) {
-    skipUntil(tok::r_square);
-    if (Tok.is(tok::r_square))
-      consumeToken();
-    return FirstExpr;
+  bool ParseDict;
+  {
+    BacktrackingScope Scope(*this);
+    // Disable the syntax tree creation in the context.
+    SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
+    auto HasDelayedDecl = State->hasDelayedDecl();
+    // Parse the first expression.
+    ParserResult<Expr> FirstExpr
+      = parseExpr(diag::expected_expr_in_collection_literal);
+    if (FirstExpr.isNull() || Tok.is(tok::eof)) {
+      skipUntil(tok::r_square);
+      if (Tok.is(tok::r_square))
+        consumeToken();
+      Scope.cancelBacktrack();
+      ArrayOrDictContext.setContextKind(SyntaxContextKind::Expr);
+      return FirstExpr;
+    }
+    if (!HasDelayedDecl)
+      State->takeDelayedDeclState();
+    // If we have a ':', this is a dictionary literal.
+    ParseDict = Tok.is(tok::colon);
   }
-
-  // If we have a ':', this is a dictionary literal.
-  if (Tok.is(tok::colon)) {
-    return parseExprDictionary(LSquareLoc, FirstExpr);
+  if (ParseDict) {
+    ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
+    return parseExprDictionary(LSquareLoc);
+  } else {
+    ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
+    return parseExprArray(LSquareLoc);
   }
-
-  // Otherwise, we have an array literal.
-  return parseExprArray(LSquareLoc, FirstExpr);
 }
 
 /// parseExprArray - Parse an array literal expression.
@@ -3131,26 +3185,18 @@
 ///   expr-array:
 ///     '[' expr (',' expr)* ','? ']'
 ///     '[' ']'
-ParserResult<Expr> Parser::parseExprArray(SourceLoc LSquareLoc,
-                                          ParserResult<Expr> FirstExpr) {
+ParserResult<Expr> Parser::parseExprArray(SourceLoc LSquareLoc) {
   SmallVector<Expr *, 8> SubExprs;
   SmallVector<SourceLoc, 8> CommaLocs;
-  SubExprs.push_back(FirstExpr.get());
 
-  SourceLoc CommaLoc, RSquareLoc;
-  ParserStatus Status(FirstExpr);
-
-  if (Tok.isNot(tok::r_square) && !consumeIf(tok::comma, CommaLoc)) {
-    diagnose(Tok, diag::expected_separator, ",")
-        .fixItInsertAfter(PreviousLoc, ",");
-    Status.setIsParseError();
-  }
-
-  CommaLocs.push_back(CommaLoc);
-
+  SourceLoc RSquareLoc;
+  ParserStatus Status;
+  bool First = true;
+  bool HasError = false;
   Status |= parseList(tok::r_square, LSquareLoc, RSquareLoc,
                       /*AllowSepAfterLast=*/true,
                       diag::expected_rsquare_array_expr,
+                      SyntaxKind::ArrayElementList,
                       [&] () -> ParserStatus
   {
     ParserResult<Expr> Element
@@ -3158,11 +3204,21 @@
     if (Element.isNonNull())
       SubExprs.push_back(Element.get());
 
+    if (First) {
+      if (Tok.isNot(tok::r_square) && Tok.isNot(tok::comma)) {
+        diagnose(Tok, diag::expected_separator, ",").
+          fixItInsertAfter(PreviousLoc, ",");
+        HasError = true;
+      }
+      First = false;
+    }
+
     if (Tok.is(tok::comma))
       CommaLocs.push_back(Tok.getLoc());
-
     return Element;
   });
+  if (HasError)
+    Status.setIsParseError();
 
   assert(SubExprs.size() >= 1);
   return makeParserResult(Status,
@@ -3178,10 +3234,7 @@
 ///   expr-dictionary:
 ///     '[' expr ':' expr (',' expr ':' expr)* ','? ']'
 ///     '[' ':' ']'
-ParserResult<Expr> Parser::parseExprDictionary(SourceLoc LSquareLoc,
-                                               ParserResult<Expr> FirstKey) {
-  assert(Tok.is(tok::colon));
-
+ParserResult<Expr> Parser::parseExprDictionary(SourceLoc LSquareLoc) {
   // Each subexpression is a (key, value) tuple.
   // FIXME: We're not tracking the colon locations in the AST.
   SmallVector<Expr *, 8> SubExprs;
@@ -3193,23 +3246,19 @@
     SubExprs.push_back(TupleExpr::createImplicit(Context, Exprs, { }));
   };
 
-  bool FirstPair = true;
-
-  ParserStatus Status(FirstKey);
+  ParserStatus Status;
   Status |=
       parseList(tok::r_square, LSquareLoc, RSquareLoc,
                 /*AllowSepAfterLast=*/true,
-                diag::expected_rsquare_array_expr, [&]() -> ParserStatus {
+                diag::expected_rsquare_array_expr,
+                SyntaxKind::DictionaryElementList,
+                [&]() -> ParserStatus {
     // Parse the next key.
     ParserResult<Expr> Key;
-    if (FirstPair) {
-      Key = makeParserResult(FirstKey.get());
-      FirstPair = false;
-    } else {
-      Key = parseExpr(diag::expected_key_in_dictionary_literal);
-      if (Key.isNull())
-        return Key;
-    }
+
+    Key = parseExpr(diag::expected_key_in_dictionary_literal);
+    if (Key.isNull())
+      return Key;
 
     // Parse the ':'.
     if (Tok.isNot(tok::colon)) {
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 09c2496..352e927 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -19,10 +19,15 @@
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/Initializer.h"
 #include "swift/Basic/StringExtras.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/SaveAndRestore.h"
+
 using namespace swift;
+using namespace swift::syntax;
 
 /// \brief Determine the kind of a default argument given a parsed
 /// expression that has not yet been type-checked.
@@ -162,6 +167,7 @@
   return parseList(tok::r_paren, leftParenLoc, rightParenLoc,
                       /*AllowSepAfterLast=*/false,
                       diag::expected_rparen_parameter,
+                      SyntaxKind::Unknown,
                       [&]() -> ParserStatus {
     ParsedParameter param;
     ParserStatus status;
@@ -795,7 +801,8 @@
                                             /*isExprBasic=*/false,
                                             lParenLoc, args, argLabels,
                                             argLabelLocs, rParenLoc,
-                                            trailingClosure);
+                                            trailingClosure,
+                                            SyntaxKind::Unknown);
         if (status.isSuccess()) {
           backtrack.cancelBacktrack();
           
@@ -947,6 +954,7 @@
     parseList(tok::r_paren, LPLoc, RPLoc,
               /*AllowSepAfterLast=*/false,
               diag::expected_rparen_tuple_pattern_list,
+              SyntaxKind::Unknown,
               [&] () -> ParserStatus {
     // Parse the pattern tuple element.
     ParserStatus EltStatus;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index aa7059c..5a91fae 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -592,17 +592,14 @@
   }
   SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
   SourceLoc LBLoc = consumeToken(tok::l_brace);
-  LocalContext.addTokenSyntax(LBLoc);
 
   SmallVector<ASTNode, 16> Entries;
   SourceLoc RBLoc;
 
   ParserStatus Status = parseBraceItems(Entries, BraceItemListKind::Brace,
                                         BraceItemListKind::Brace);
-  if (!parseMatchingToken(tok::r_brace, RBLoc,
-                          diag::expected_rbrace_in_brace_stmt, LBLoc)) {
-    LocalContext.addTokenSyntax(RBLoc);
-  }
+  parseMatchingToken(tok::r_brace, RBLoc,
+                     diag::expected_rbrace_in_brace_stmt, LBLoc);
 
   return makeParserResult(Status,
                           BraceStmt::create(Context, LBLoc, Entries, RBLoc));
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index bf66864..9721141 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -15,10 +15,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "swift/Parse/Parser.h"
+#include "swift/AST/ASTWalker.h"
 #include "swift/AST/Attr.h"
 #include "swift/AST/TypeLoc.h"
 #include "swift/Parse/Lexer.h"
 #include "swift/Parse/CodeCompletionCallbacks.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
@@ -26,6 +30,7 @@
 #include "llvm/Support/SaveAndRestore.h"
 
 using namespace swift;
+using namespace swift::syntax;
 
 TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
                                        const TypeAttributes &attrs,
@@ -794,6 +799,7 @@
   ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
                                   /*AllowSepAfterLast=*/false,
                                   diag::expected_rparen_tuple_type_list,
+                                  SyntaxKind::Unknown,
                                   [&] () -> ParserStatus {
     TupleTypeReprElement element;
 
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a5d5c6d..b90d5f8 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -35,6 +35,7 @@
 #include "llvm/ADT/Twine.h"
 
 using namespace swift;
+using namespace swift::syntax;
 
 void DelayedParsingCallbacks::anchor() { }
 void SILParserTUStateBase::anchor() { }
@@ -127,6 +128,14 @@
 }
 } // unnamed namespace
 
+
+swift::Parser::BacktrackingScope::~BacktrackingScope() {
+  if (Backtrack) {
+    P.backtrackToPosition(PP);
+    DT.abort();
+  }
+}
+
 void swift::performDelayedParsing(
     DeclContext *DC, PersistentParserState &PersistentState,
     CodeCompletionCallbacksFactory *CodeCompletionFactory) {
@@ -438,8 +447,8 @@
     TokReceiver(SF.shouldKeepSyntaxInfo() ?
                 new TokenRecorder(SF) :
                 new ConsumeTokenReceiver()),
-    SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(), Tok)) {
-
+    SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(),
+                                                       Tok)) {
   State = PersistentState;
   if (!State) {
     OwnedState.reset(new PersistentParserState());
@@ -817,12 +826,33 @@
   return false;
 }
 
+static Optional<SyntaxKind> getListElementKind(SyntaxKind ListKind) {
+  switch (ListKind) {
+  case SyntaxKind::FunctionCallArgumentList:
+    return SyntaxKind::FunctionCallArgument;
+  case SyntaxKind::ArrayElementList:
+    return SyntaxKind::ArrayElement;
+  case SyntaxKind::DictionaryElementList:
+    return SyntaxKind::DictionaryElement;
+  default:
+    return None;
+  }
+}
+
 ParserStatus
 Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
-                  bool AllowSepAfterLast, Diag<> ErrorDiag,
+                  bool AllowSepAfterLast, Diag<> ErrorDiag, SyntaxKind Kind,
                   std::function<ParserStatus()> callback) {
+  SyntaxParsingContextChild ListContext(SyntaxContext);
+  Optional<SyntaxKind> ElementKind = getListElementKind(Kind);
+  if (ElementKind)
+    ListContext.setSyntaxKind(Kind);
+  else
+    // FIXME: we shouldn't need this when all cases are handled.
+    ListContext.disable();
 
   if (Tok.is(RightK)) {
+    ListContext.finalize();
     RightLoc = consumeToken(RightK);
     return makeParserSuccess();
   }
@@ -835,6 +865,12 @@
       consumeToken();
     }
     SourceLoc StartLoc = Tok.getLoc();
+    SyntaxParsingContextChild ElementContext(SyntaxContext);
+    if (ElementKind) {
+      ElementContext.setSyntaxKind(*ElementKind);
+    } else {
+      ElementContext.disable();
+    }
     Status |= callback();
     if (Tok.is(RightK))
       break;
@@ -878,6 +914,7 @@
     Status.setIsParseError();
   }
 
+  ListContext.finalize();
   if (Status.isError()) {
     // If we've already got errors, don't emit missing RightK diagnostics.
     RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index cc7166e..675615d 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -28,10 +28,13 @@
 #include "swift/SIL/SILModule.h"
 #include "swift/SIL/SILUndef.h"
 #include "swift/SIL/TypeLowering.h"
+#include "swift/Syntax/SyntaxKind.h"
 #include "swift/Subsystems.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/SaveAndRestore.h"
+
 using namespace swift;
+using namespace swift::syntax;
 
 //===----------------------------------------------------------------------===//
 // SILParserState implementation
@@ -875,7 +878,9 @@
 static bool parseDeclSILOptional(bool *isTransparent,
                                  IsSerialized_t *isSerialized,
                                  IsThunk_t *isThunk, bool *isGlobalInit,
-                                 Inline_t *inlineStrategy, bool *isLet,
+                                 Inline_t *inlineStrategy,
+                                 OptimizationMode *optimizationMode,
+                                 bool *isLet,
                                  SmallVectorImpl<std::string> *Semantics,
                                  SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
                                  ValueDecl **ClangDecl,
@@ -904,6 +909,12 @@
       *isGlobalInit = true;
     else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
       *inlineStrategy = NoInline;
+    else if (optimizationMode && SP.P.Tok.getText() == "Onone")
+      *optimizationMode = OptimizationMode::NoOptimization;
+    else if (optimizationMode && SP.P.Tok.getText() == "Ospeed")
+      *optimizationMode = OptimizationMode::ForSpeed;
+    else if (optimizationMode && SP.P.Tok.getText() == "Osize")
+      *optimizationMode = OptimizationMode::ForSize;
     else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
       *inlineStrategy = AlwaysInline;
     else if (MRK && SP.P.Tok.getText() == "readnone")
@@ -1236,7 +1247,7 @@
   if (!P.consumeIf(tok::sil_exclamation)) {
     // Construct SILDeclRef.
     Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
-    if (uncurryLevel < Result.getUncurryLevel())
+    if (uncurryLevel < Result.getParameterListCount() - 1)
       Result = Result.asCurried();
     return false;
   }
@@ -1327,7 +1338,7 @@
 
   // Construct SILDeclRef.
   Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
-  if (uncurryLevel < Result.getUncurryLevel())
+  if (uncurryLevel < Result.getParameterListCount() - 1)
     Result = Result.asCurried();
   return false;
 }
@@ -1462,6 +1473,7 @@
     if (P.parseList(tok::r_paren, LParenLoc, RParenLoc,
                     /*AllowSepAfterLast=*/false,
                     diag::sil_basicblock_arg_rparen,
+                    SyntaxKind::Unknown,
                     [&]() -> ParserStatus {
                       SILValue Arg;
                       SourceLoc ArgLoc;
@@ -1938,11 +1950,30 @@
     break;
   }
   case SILInstructionKind::ApplyInst:
+  case SILInstructionKind::BeginApplyInst:
   case SILInstructionKind::PartialApplyInst:
   case SILInstructionKind::TryApplyInst:
     if (parseCallInstruction(InstLoc, Opcode, B, ResultVal))
       return true;
     break;
+  case SILInstructionKind::AbortApplyInst:
+  case SILInstructionKind::EndApplyInst: {
+    UnresolvedValueName argName;
+    if (parseValueName(argName)) return true;
+
+    if (parseSILDebugLocation(InstLoc, B))
+      return true;
+
+    SILType expectedTy = SILType::getSILTokenType(P.Context);
+    SILValue op = getLocalValue(argName, expectedTy, InstLoc, B);
+
+    if (Opcode == SILInstructionKind::AbortApplyInst) {
+      ResultVal = B.createAbortApply(InstLoc, op);
+    } else {
+      ResultVal = B.createEndApply(InstLoc, op);
+    }
+    break;
+  }
   case SILInstructionKind::IntegerLiteralInst: {
     SILType Ty;
     if (parseSILType(Ty) ||
@@ -3735,6 +3766,51 @@
     ResultVal = B.createThrow(InstLoc, Val);
     break;
   }
+  case SILInstructionKind::UnwindInst: {
+    if (parseSILDebugLocation(InstLoc, B))
+      return true;
+    ResultVal = B.createUnwind(InstLoc);
+    break;
+  }
+  case SILInstructionKind::YieldInst: {
+    SmallVector<SILValue, 6> values;
+
+    // Parse a parenthesized (unless length-1), comma-separated list
+    // of yielded values.
+    if (P.consumeIf(tok::l_paren)) {
+      do {
+        if (parseTypedValueRef(Val, B))
+          return true;
+        values.push_back(Val);
+      } while (P.consumeIf(tok::comma));
+
+      if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
+        return true;
+
+    } else {
+      if (parseTypedValueRef(Val, B))
+        return true;
+      values.push_back(Val);
+    }
+
+    Identifier resumeName, unwindName;
+    SourceLoc resumeLoc, unwindLoc;
+    if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+        parseVerbatim("resume") ||
+        parseSILIdentifier(resumeName, resumeLoc,
+                           diag::expected_sil_block_name) ||
+        P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+        parseVerbatim("unwind") ||
+        parseSILIdentifier(unwindName, unwindLoc,
+                           diag::expected_sil_block_name) ||
+        parseSILDebugLocation(InstLoc, B))
+      return true;
+
+    auto resumeBB = getBBForReference(resumeName, resumeLoc);
+    auto unwindBB = getBBForReference(unwindName, unwindLoc);
+    ResultVal = B.createYield(InstLoc, values, resumeBB, unwindBB);
+    break;
+  }
   case SILInstructionKind::BranchInst: {
     Identifier BBName;
     SourceLoc NameLoc;
@@ -4677,17 +4753,39 @@
   }
   SILFunctionConventions substConv(substFTI, B.getModule());
 
+  // Validate the operand count.
+  if (substConv.getNumSILArguments() != ArgNames.size() &&
+      Opcode != SILInstructionKind::PartialApplyInst) {
+    P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+               "to have the same number of arg names as arg types");
+    return true;
+  }
+
+  // Validate the coroutine kind.
+  if (Opcode == SILInstructionKind::ApplyInst ||
+      Opcode == SILInstructionKind::TryApplyInst) {
+    if (FTI->getCoroutineKind() != SILCoroutineKind::None) {
+      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+                 "to not be a coroutine");
+      return true;
+    }
+  } else if (Opcode == SILInstructionKind::BeginApplyInst) {
+    if (FTI->getCoroutineKind() != SILCoroutineKind::YieldOnce) {
+      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+                 "to be a yield_once coroutine");
+      return true;
+    }
+  } else {
+    assert(Opcode == SILInstructionKind::PartialApplyInst);
+    // partial_apply accepts all kinds of function
+  }
+
   switch (Opcode) {
   default: llvm_unreachable("Unexpected case");
   case SILInstructionKind::ApplyInst : {
     if (parseSILDebugLocation(InstLoc, B))
       return true;
-    if (substConv.getNumSILArguments() != ArgNames.size()) {
-      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
-                 "to have the same number of arg names as arg types");
-      return true;
-    }
-    
+
     unsigned ArgNo = 0;
     SmallVector<SILValue, 4> Args;
     for (auto &ArgName : ArgNames) {
@@ -4698,14 +4796,25 @@
     ResultVal = B.createApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
     break;
   }
+  case SILInstructionKind::BeginApplyInst: {
+    if (parseSILDebugLocation(InstLoc, B))
+      return true;
+    
+    unsigned ArgNo = 0;
+    SmallVector<SILValue, 4> Args;
+    for (auto &ArgName : ArgNames) {
+      SILType expectedTy = substConv.getSILArgumentType(ArgNo++);
+      Args.push_back(getLocalValue(ArgName, expectedTy, InstLoc, B));
+    }
+
+    ResultVal =
+      B.createBeginApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
+    ResultVal->dump();
+    break;
+  }
   case SILInstructionKind::PartialApplyInst: {
     if (parseSILDebugLocation(InstLoc, B))
       return true;
-    if (substFTI->getParameters().size() < ArgNames.size()) {
-      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
-                 "have the right argument types");
-      return true;
-    }
 
     // Compute the result type of the partial_apply, based on which arguments
     // are getting applied.
@@ -4735,12 +4844,6 @@
         parseSILDebugLocation(InstLoc, B))
       return true;
 
-    if (substConv.getNumSILArguments() != ArgNames.size()) {
-      P.diagnose(TypeLoc, diag::expected_sil_type_kind,
-                 "to have the same number of arg names as arg types");
-      return true;
-    }
-    
     unsigned argNo = 0;
     SmallVector<SILValue, 4> args;
     for (auto &argName : ArgNames) {
@@ -4917,13 +5020,15 @@
   IsThunk_t isThunk = IsNotThunk;
   bool isGlobalInit = false;
   Inline_t inlineStrategy = InlineDefault;
+  OptimizationMode optimizationMode = OptimizationMode::NotSet;
   SmallVector<std::string, 1> Semantics;
   SmallVector<ParsedSpecAttr, 4> SpecAttrs;
   ValueDecl *ClangDecl = nullptr;
   EffectsKind MRK = EffectsKind::Unspecified;
   if (parseSILLinkage(FnLinkage, P) ||
       parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
-                           &inlineStrategy, nullptr, &Semantics, &SpecAttrs,
+                           &inlineStrategy, &optimizationMode, nullptr,
+                           &Semantics, &SpecAttrs,
                            &ClangDecl, &MRK, FunctionState) ||
       P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
       P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -4950,6 +5055,7 @@
     FunctionState.F->setThunk(IsThunk_t(isThunk));
     FunctionState.F->setGlobalInit(isGlobalInit);
     FunctionState.F->setInlineStrategy(inlineStrategy);
+    FunctionState.F->setOptimizationMode(optimizationMode);
     FunctionState.F->setEffectsKind(MRK);
     if (ClangDecl)
       FunctionState.F->setClangNodeOwner(ClangDecl);
@@ -5078,7 +5184,7 @@
   SILParser State(P);
   if (parseSILLinkage(GlobalLinkage, P) ||
       parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
-                           nullptr, &isLet, nullptr, nullptr, nullptr,
+                           nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
                            nullptr, State) ||
       P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
       P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
@@ -5121,7 +5227,7 @@
 
   IsSerialized_t Serialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
-                           nullptr, nullptr, nullptr, nullptr, nullptr,
+                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                            nullptr, VTableState))
     return true;
 
@@ -5470,7 +5576,7 @@
   
   IsSerialized_t isSerialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
-                           nullptr, nullptr, nullptr, nullptr, nullptr,
+                           nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
                            nullptr, WitnessState))
     return true;
 
@@ -5522,6 +5628,8 @@
   Lexer::SILBodyRAII Tmp(*P.L);
   // Parse the entry list.
   std::vector<SILWitnessTable::Entry> witnessEntries;
+  std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;
+
   if (P.Tok.isNot(tok::r_brace)) {
     do {
       Identifier EntryKeyword;
@@ -5547,7 +5655,8 @@
         continue;
       }
 
-      if (EntryKeyword.str() == "associated_type_protocol") {
+      if (EntryKeyword.str() == "associated_type_protocol" ||
+          EntryKeyword.str() == "conditional_conformance") {
         if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
           return true;
         CanType assoc = parseAssociatedTypePath(P, WitnessState, proto);
@@ -5572,9 +5681,14 @@
           P.consumeToken();
         }
 
-        witnessEntries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
-          assoc, proto, conformance
-        });
+        if (EntryKeyword.str() == "associated_type_protocol")
+          witnessEntries.push_back(
+              SILWitnessTable::AssociatedTypeProtocolWitness{assoc, proto,
+                                                             conformance});
+        else
+          conditionalConformances.push_back(
+              SILWitnessTable::ConditionalConformance{assoc, conformance});
+
         continue;
       }
 
@@ -5647,7 +5761,8 @@
 
   if (!wt)
     wt = SILWitnessTable::create(M, *Linkage, theConformance);
-  wt->convertToDefinition(witnessEntries, isSerialized);
+  wt->convertToDefinition(witnessEntries, conditionalConformances,
+                          isSerialized);
   BodyScope.reset();
   return false;
 }
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 064af07..5dcf23e 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -334,7 +334,12 @@
 
       auto label = Ctx.getIdentifier(param.getLabel());
       auto flags = param.getFlags();
-      funcParams.push_back(AnyFunctionType::Param(type, label, flags));
+      auto parameterFlags = ParameterTypeFlags()
+                                .withInOut(flags.isInOut())
+                                .withShared(flags.isShared())
+                                .withVariadic(flags.isVariadic());
+
+      funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
     }
 
     return FunctionType::get(funcParams, output, einfo);
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 669c0d3..48e6546 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -151,6 +151,11 @@
     return DynamicCastFeasibility::WillFail;
   }
 
+  // AnyHashable is a special case: although it's a struct, there maybe another
+  // type conforming to it and to the TargetProtocol at the same time.
+  if (SourceNominalTy == SourceNominalTy->getASTContext().getAnyHashableDecl())
+    return DynamicCastFeasibility::MaySucceed;
+
   // If we are in a whole-module compilation and
   // if the source type is internal or target protocol is internal,
   // then conformances cannot be changed at run-time, because only this
diff --git a/lib/SIL/OptimizationRemark.cpp b/lib/SIL/OptimizationRemark.cpp
index 87f8b26..c62a5fc 100644
--- a/lib/SIL/OptimizationRemark.cpp
+++ b/lib/SIL/OptimizationRemark.cpp
@@ -19,6 +19,7 @@
 #include "swift/SIL/OptimizationRemark.h"
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/AST/DiagnosticsSIL.h"
+#include "swift/Demangling/Demangler.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
@@ -43,7 +44,13 @@
     : Key(Key), Val(llvm::utostr(N)) {}
 
 Argument::Argument(StringRef Key, SILFunction *F)
-    : Key(Key), Val(F->getName()) {
+    : Key(Key),
+      Val((Twine("\"") +
+           Demangle::demangleSymbolAsString(
+               F->getName(),
+               Demangle::DemangleOptions::SimplifiedUIDemangleOptions()) +
+           "\"")
+              .str()) {
   if (F->hasLocation())
     Loc = F->getLocation().getSourceLoc();
 }
@@ -70,6 +77,8 @@
 template <typename RemarkT, typename... ArgTypes>
 static void emitRemark(SILModule &Module, const Remark<RemarkT> &R,
                        Diag<ArgTypes...> ID, bool DiagEnabled) {
+  if (R.getLocation().isInvalid())
+    return;
   if (auto *Out = Module.getOptRecordStream())
     // YAMLTraits takes a non-const reference even when outputting.
     *Out << const_cast<Remark<RemarkT> &>(R);
@@ -110,7 +119,9 @@
     if (!io.outputting() || Loc.isValid())
       io.mapOptional("DebugLoc", Loc);
 
-    StringRef FN = R.getFunction()->getName();
+    std::string FN = Demangle::demangleSymbolAsString(
+        R.getFunction()->getName(),
+        Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
     io.mapRequired("Function", FN);
     io.mapOptional("Args", R.getArgs());
   }
diff --git a/lib/SIL/SILArgument.cpp b/lib/SIL/SILArgument.cpp
index dfd1686..87ed4af 100644
--- a/lib/SIL/SILArgument.cpp
+++ b/lib/SIL/SILArgument.cpp
@@ -73,12 +73,14 @@
   case TermKind::UnreachableInst:
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
+  case TermKind::UnwindInst:
     llvm_unreachable("Have terminator that implies no successors?!");
   case TermKind::TryApplyInst:
   case TermKind::SwitchValueInst:
   case TermKind::SwitchEnumAddrInst:
   case TermKind::CheckedCastAddrBranchInst:
   case TermKind::DynamicMethodBranchInst:
+  case TermKind::YieldInst:
     return SILValue();
   case TermKind::BranchInst:
     return cast<const BranchInst>(TI)->getArg(Index);
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 06d7bff..aa65f47 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -79,8 +79,10 @@
   }
 
   auto appliedFnType = SILFunctionType::get(nullptr, extInfo,
+                                            FTI->getCoroutineKind(),
                                             calleeConvention,
                                             newParams,
+                                            FTI->getYields(),
                                             results,
                                             FTI->getOptionalErrorResult(),
                                             M.getASTContext());
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 1acb152..e7ac325 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -227,29 +227,6 @@
   return false;
 }
 
-static unsigned getFuncNaturalUncurryLevel(AnyFunctionRef AFR) {
-  assert(AFR.getParameterLists().size() >= 1 && "no arguments for func?!");
-  return AFR.getParameterLists().size() - 1;
-}
-
-unsigned swift::getNaturalUncurryLevel(ValueDecl *vd) {
-  if (auto *func = dyn_cast<FuncDecl>(vd)) {
-    return getFuncNaturalUncurryLevel(func);
-  } else if (isa<ConstructorDecl>(vd)) {
-    return 1;
-  } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
-    return ed->hasAssociatedValues() ? 1 : 0;
-  } else if (isa<DestructorDecl>(vd)) {
-    return 0;
-  } else if (isa<ClassDecl>(vd)) {
-    return 1;
-  } else if (isa<VarDecl>(vd)) {
-    return 0;
-  } else {
-    llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
-  }
-}
-
 SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
                        ResilienceExpansion expansion,
                        bool isCurried, bool isForeign)
@@ -709,6 +686,10 @@
     case SILDeclRef::ManglingKind::DynamicThunk:
       SKind = ASTMangler::SymbolKind::DynamicThunk;
       break;
+    case SILDeclRef::ManglingKind::SwiftDispatchThunk:
+      assert(!isForeign && !isDirectReference && !isCurried);
+      SKind = ASTMangler::SymbolKind::SwiftDispatchThunk;
+      break;
   }
 
   switch (kind) {
@@ -795,6 +776,22 @@
   llvm_unreachable("bad entity kind!");
 }
 
+bool SILDeclRef::requiresNewVTableEntry() const {
+  if (cast<AbstractFunctionDecl>(getDecl())->needsNewVTableEntry())
+    return true;
+  if (kind == SILDeclRef::Kind::Allocator) {
+    auto *cd = cast<ConstructorDecl>(getDecl());
+    if (cd->isRequired()) {
+      auto *baseCD = cd->getOverriddenDecl();
+      if(!baseCD ||
+         !baseCD->isRequired() ||
+         baseCD->hasClangNode())
+        return true;
+    }
+  }
+  return false;
+}
+
 SILDeclRef SILDeclRef::getOverridden() const {
   if (!hasDecl())
     return SILDeclRef();
@@ -888,12 +885,23 @@
   llvm_unreachable("Unhandled access level in switch.");
 }
 
-unsigned SILDeclRef::getUncurryLevel() const {
-  if (isCurried)
-    return 0;
-  if (!hasDecl())
-    return getFuncNaturalUncurryLevel(*getAnyFunctionRef());
-  if (kind == Kind::DefaultArgGenerator)
-    return 0;
-  return getNaturalUncurryLevel(getDecl());
+unsigned SILDeclRef::getParameterListCount() const {
+  if (isCurried || !hasDecl() || kind == Kind::DefaultArgGenerator)
+    return 1;
+
+  auto *vd = getDecl();
+
+  if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
+    return func->getParameterLists().size();
+  } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
+    return ed->hasAssociatedValues() ? 2 : 1;
+  } else if (isa<DestructorDecl>(vd)) {
+    return 1;
+  } else if (isa<ClassDecl>(vd)) {
+    return 2;
+  } else if (isa<VarDecl>(vd)) {
+    return 1;
+  } else {
+    llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
+  }
 }
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index ec909fd..4212375 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -18,6 +18,7 @@
 #include "swift/SIL/CFG.h"
 #include "swift/SIL/PrettyStackTrace.h"
 #include "swift/AST/GenericEnvironment.h"
+#include "swift/Basic/OptimizationMode.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/GraphWriter.h"
@@ -96,7 +97,8 @@
       Serialized(isSerialized), Thunk(isThunk),
       ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
       InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
-      HasCReferences(false), KeepAsPublic(false), EffectsKindAttr(E),
+      HasCReferences(false), KeepAsPublic(false),
+      OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
       EntryCount(entryCount) {
   if (InsertBefore)
     Module.functions.insert(SILModule::iterator(InsertBefore), this);
@@ -168,10 +170,16 @@
   return getModule().getASTContext();
 }
 
+OptimizationMode SILFunction::getEffectiveOptimizationMode() const {
+  if (OptMode != OptimizationMode::NotSet)
+    return OptMode;
+
+  return getModule().getOptions().OptMode;
+}
+
 bool SILFunction::shouldOptimize() const {
-  if (Module.getStage() == SILStage::Raw)
-    return true;
-  return !hasSemanticsAttr("optimize.sil.never");
+  return !hasSemanticsAttr("optimize.sil.never") &&
+         getEffectiveOptimizationMode() != OptimizationMode::NoOptimization;
 }
 
 Type SILFunction::mapTypeIntoContext(Type type) const {
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 29c2e2e..b55264e 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -196,10 +196,13 @@
       type->getWitnessMethodConformanceOrNone() == witnessMethodConformance)
     return type;
 
-  return SILFunctionType::get(type->getGenericSignature(), extInfo, callee,
-                              type->getParameters(), type->getResults(),
+  return SILFunctionType::get(type->getGenericSignature(),
+                              extInfo, type->getCoroutineKind(), callee,
+                              type->getParameters(), type->getYields(),
+                              type->getResults(),
                               type->getOptionalErrorResult(),
-                              type->getASTContext(), witnessMethodConformance);
+                              type->getASTContext(),
+                              witnessMethodConformance);
 }
 
 namespace {
@@ -960,7 +963,8 @@
     .withIsPseudogeneric(pseudogeneric)
     .withNoEscape(extInfo.isNoEscape());
   
-  return SILFunctionType::get(genericSig, silExtInfo, calleeConvention, inputs,
+  return SILFunctionType::get(genericSig, silExtInfo, SILCoroutineKind::None,
+                              calleeConvention, inputs, /*yields*/ {},
                               results, errorResult, M.getASTContext(),
                               witnessMethodConformance);
 }
@@ -1777,7 +1781,7 @@
     return false;
 
   // Must be a type member.
-  if (constant.getUncurryLevel() != 1)
+  if (constant.getParameterListCount() != 2)
     return false;
 
   // Must be imported from a function.
@@ -2005,20 +2009,6 @@
   return ty->getParameters().back();
 }
 
-static bool requiresNewVTableEntry(SILDeclRef method) {
-  if (cast<AbstractFunctionDecl>(method.getDecl())->needsNewVTableEntry())
-    return true;
-  if (method.kind == SILDeclRef::Kind::Allocator) {
-    auto *ctor = cast<ConstructorDecl>(method.getDecl());
-    if (ctor->isRequired()) {
-      if (!ctor->getOverriddenDecl()->isRequired()
-          || ctor->getOverriddenDecl()->hasClangNode())
-        return true;
-    }
-  }
-  return false;
-}
-
 // This check duplicates TypeConverter::checkForABIDifferences(),
 // but on AST types. The issue is we only want to introduce a new
 // vtable thunk if the AST type changes, but an abstraction change
@@ -2034,7 +2024,7 @@
   SILDeclRef cur = method, next = method;
   do {
     cur = next;
-    if (requiresNewVTableEntry(cur))
+    if (cur.requiresNewVTableEntry())
       return cur;
     next = cur.getNextOverriddenVTableEntry();
   } while (next);
@@ -2112,7 +2102,7 @@
   if (found != ConstantOverrideTypes.end())
     return *found->second;
 
-  assert(requiresNewVTableEntry(base) && "base must not be an override");
+  assert(base.requiresNewVTableEntry() && "base must not be an override");
 
   auto baseInfo = getConstantInfo(base);
   auto derivedInfo = getConstantInfo(derived);
@@ -2235,6 +2225,12 @@
         substParams.push_back(subst(origParam));
       }
 
+      SmallVector<SILYieldInfo, 8> substYields;
+      substYields.reserve(origType->getYields().size());
+      for (auto &origYield : origType->getYields()) {
+        substYields.push_back(subst(origYield));
+      }
+
       Optional<ProtocolConformanceRef> witnessMethodConformance;
       if (auto conformance = origType->getWitnessMethodConformanceOrNone()) {
         assert(origType->getExtInfo().hasSelfParam());
@@ -2253,8 +2249,9 @@
       }
 
       return SILFunctionType::get(nullptr, origType->getExtInfo(),
+                                  origType->getCoroutineKind(),
                                   origType->getCalleeConvention(), substParams,
-                                  substResults, substErrorResult,
+                                  substYields, substResults, substErrorResult,
                                   getASTContext(), witnessMethodConformance);
     }
 
@@ -2267,6 +2264,10 @@
       return SILResultInfo(visit(orig.getType()), orig.getConvention());
     }
 
+    SILYieldInfo subst(SILYieldInfo orig) {
+      return SILYieldInfo(visit(orig.getType()), orig.getConvention());
+    }
+
     SILParameterInfo subst(SILParameterInfo orig) {
       return SILParameterInfo(visit(orig.getType()), orig.getConvention());
     }
@@ -2486,7 +2487,7 @@
 TypeConverter::LoweredFormalTypes
 TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
                                      CanAnyFunctionType fnType) {
-  unsigned uncurryLevel = constant.getUncurryLevel();
+  unsigned uncurryLevel = constant.getParameterListCount() - 1;
   auto extInfo = fnType->getExtInfo();
 
   // Form an abstraction pattern for bridging purposes.
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 589b5c1..2e247bf 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -1335,10 +1335,25 @@
   return iterator(*this, getEndOffset());
 }
 
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rbegin() const {
+  return llvm::make_reverse_iterator(end());
+}
+
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rend() const {
+  return llvm::make_reverse_iterator(begin());
+}
+
 SILInstructionResultArray::range SILInstructionResultArray::getValues() const {
   return {begin(), end()};
 }
 
+SILInstructionResultArray::reverse_range
+SILInstructionResultArray::getReversedValues() const {
+  return {rbegin(), rend()};
+}
+
 const ValueBase *SILInstructionResultArray::front() const {
   assert(size() && "Can not access front of an empty result array");
   return *begin();
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 2af36c2..6f1f581 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -33,6 +33,14 @@
 using namespace swift;
 using namespace Lowering;
 
+/// Allocate an instruction that inherits from llvm::TrailingObjects<>.
+template <class Inst, class... TrailingTypes, class... CountTypes>
+static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
+  return F.getModule().allocateInst(
+             Inst::template totalSizeToAlloc<TrailingTypes...>(counts...),
+             alignof(Inst));
+}
+
 // Collect used open archetypes from a given type into the \p openedArchetypes.
 // \p openedArchetypes is being used as a set. We don't use a real set type here
 // for performance reasons.
@@ -403,6 +411,7 @@
     : InstructionBase(Loc, Callee, SubstCalleeTy, Subs, Args,
                       TypeDependentOperands, SpecializationInfo, Result) {
   setNonThrowing(isNonThrowing);
+  assert(!SubstCalleeTy.castTo<SILFunctionType>()->isCoroutine());
 }
 
 ApplyInst *
@@ -423,13 +432,77 @@
   SmallVector<SILValue, 32> TypeDependentOperands;
   collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
                                SubstCalleeSILTy.getSwiftRValueType(), Subs);
-  void *Buffer = allocate(F, Subs, TypeDependentOperands, Args);
+  void *Buffer =
+    allocateTrailingInst<ApplyInst, Operand, Substitution>(
+      F, getNumAllOperands(Args, TypeDependentOperands), Subs.size());
   return ::new(Buffer) ApplyInst(Loc, Callee, SubstCalleeSILTy,
                                  Result, Subs, Args,
                                  TypeDependentOperands, isNonThrowing,
                                  SpecializationInfo);
 }
 
+BeginApplyInst::BeginApplyInst(SILDebugLocation loc, SILValue callee,
+                               SILType substCalleeTy,
+                               ArrayRef<SILType> allResultTypes,
+                               ArrayRef<ValueOwnershipKind> allResultOwnerships,
+                               SubstitutionList subs,
+                               ArrayRef<SILValue> args,
+                               ArrayRef<SILValue> typeDependentOperands,
+                               bool isNonThrowing,
+                     const GenericSpecializationInformation *specializationInfo)
+    : InstructionBase(loc, callee, substCalleeTy, subs, args,
+                      typeDependentOperands, specializationInfo),
+      MultipleValueInstructionTrailingObjects(this, allResultTypes,
+                                              allResultOwnerships) {
+  setNonThrowing(isNonThrowing);
+  assert(substCalleeTy.castTo<SILFunctionType>()->isCoroutine());
+}
+
+BeginApplyInst *
+BeginApplyInst::create(SILDebugLocation loc, SILValue callee,
+                       SubstitutionList subs, ArrayRef<SILValue> args,
+                       bool isNonThrowing,
+                       Optional<SILModuleConventions> moduleConventions,
+                       SILFunction &F,
+                       SILOpenedArchetypesState &openedArchetypes,
+                  const GenericSpecializationInformation *specializationInfo) {
+  SILType substCalleeSILType =
+      callee->getType().substGenericArgs(F.getModule(), subs);
+  auto substCalleeType = substCalleeSILType.castTo<SILFunctionType>();
+
+  SILFunctionConventions conv(substCalleeType,
+                              moduleConventions.hasValue()
+                                  ? moduleConventions.getValue()
+                                  : SILModuleConventions(F.getModule()));
+
+  SmallVector<SILType, 8> resultTypes;
+  SmallVector<ValueOwnershipKind, 8> resultOwnerships;
+
+  for (auto &yield : substCalleeType->getYields()) {
+    auto yieldType = conv.getSILType(yield);
+    auto convention = SILArgumentConvention(yield.getConvention());
+    resultTypes.push_back(yieldType);
+    resultOwnerships.push_back(
+      ValueOwnershipKind(F.getModule(), yieldType, convention));
+  }
+
+  resultTypes.push_back(SILType::getSILTokenType(F.getASTContext()));
+  resultOwnerships.push_back(ValueOwnershipKind::Trivial);
+
+  SmallVector<SILValue, 32> typeDependentOperands;
+  collectTypeDependentOperands(typeDependentOperands, openedArchetypes, F,
+                               substCalleeType, subs);
+  void *buffer =
+    allocateTrailingInst<BeginApplyInst, Operand, Substitution,
+                         MultipleValueInstruction*, BeginApplyResult>(
+      F, getNumAllOperands(args, typeDependentOperands), subs.size(),
+      1, resultTypes.size());
+  return ::new(buffer) BeginApplyInst(loc, callee, substCalleeSILType,
+                                      resultTypes, resultOwnerships, subs,
+                                      args, typeDependentOperands,
+                                      isNonThrowing, specializationInfo);
+}
+
 bool swift::doesApplyCalleeHaveSemantics(SILValue callee, StringRef semantics) {
   if (auto *FRI = dyn_cast<FunctionRefInst>(callee))
     if (auto *F = FRI->getReferencedFunction())
@@ -437,10 +510,6 @@
   return false;
 }
 
-void *swift::allocateApplyInst(SILFunction &F, size_t size, size_t alignment) {
-  return F.getModule().allocateInst(size, alignment);
-}
-
 PartialApplyInst::PartialApplyInst(
     SILDebugLocation Loc, SILValue Callee, SILType SubstCalleeTy,
     SubstitutionList Subs, ArrayRef<SILValue> Args,
@@ -467,7 +536,9 @@
   SmallVector<SILValue, 32> TypeDependentOperands;
   collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
                                SubstCalleeTy.getSwiftRValueType(), Subs);
-  void *Buffer = allocate(F, Subs, TypeDependentOperands, Args);
+  void *Buffer =
+    allocateTrailingInst<PartialApplyInst, Operand, Substitution>(
+      F, getNumAllOperands(Args, TypeDependentOperands), Subs.size());
   return ::new(Buffer) PartialApplyInst(Loc, Callee, SubstCalleeTy,
                                         Subs, Args,
                                         TypeDependentOperands, ClosureType,
@@ -491,20 +562,22 @@
                       errorBB) {}
 
 TryApplyInst *TryApplyInst::create(
-    SILDebugLocation Loc, SILValue callee, SubstitutionList subs,
+    SILDebugLocation loc, SILValue callee, SubstitutionList subs,
     ArrayRef<SILValue> args, SILBasicBlock *normalBB, SILBasicBlock *errorBB,
-    SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
-    const GenericSpecializationInformation *SpecializationInfo) {
+    SILFunction &F, SILOpenedArchetypesState &openedArchetypes,
+    const GenericSpecializationInformation *specializationInfo) {
   SILType substCalleeTy =
       callee->getType().substGenericArgs(F.getModule(), subs);
 
-  SmallVector<SILValue, 32> TypeDependentOperands;
-  collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
+  SmallVector<SILValue, 32> typeDependentOperands;
+  collectTypeDependentOperands(typeDependentOperands, openedArchetypes, F,
                                substCalleeTy.getSwiftRValueType(), subs);
-  void *buffer = allocate(F, subs, TypeDependentOperands, args);
-  return ::new (buffer) TryApplyInst(Loc, callee, substCalleeTy, subs, args,
-                                     TypeDependentOperands,
-                                     normalBB, errorBB, SpecializationInfo);
+  void *buffer =
+    allocateTrailingInst<TryApplyInst, Operand, Substitution>(
+      F, getNumAllOperands(args, typeDependentOperands), subs.size());
+  return ::new (buffer) TryApplyInst(loc, callee, substCalleeTy, subs, args,
+                                     typeDependentOperands,
+                                     normalBB, errorBB, specializationInfo);
 }
 
 FunctionRefInst::FunctionRefInst(SILDebugLocation Loc, SILFunction *F)
@@ -1056,15 +1129,33 @@
   case TermKind::CheckedCastAddrBranchInst:
   case TermKind::UnreachableInst:
   case TermKind::TryApplyInst:
+  case TermKind::YieldInst:
     return false;
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
+  case TermKind::UnwindInst:
     return true;
   }
 
   llvm_unreachable("Unhandled TermKind in switch.");
 }
 
+YieldInst::YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+                     SILBasicBlock *normalBB, SILBasicBlock *unwindBB)
+  : InstructionBase(loc),
+    DestBBs{{this, normalBB}, {this, unwindBB}},
+    Operands(this, yieldedValues) {}
+
+YieldInst *YieldInst::create(SILDebugLocation loc,
+                             ArrayRef<SILValue> yieldedValues,
+                             SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+                             SILFunction &F) {
+  void *buffer = F.getModule().allocateInst(sizeof(YieldInst) +
+                        decltype(Operands)::getExtraSize(yieldedValues.size()),
+                                            alignof(YieldInst));
+  return ::new (buffer) YieldInst(loc, yieldedValues, normalBB, unwindBB);
+}
+
 BranchInst::BranchInst(SILDebugLocation Loc, SILBasicBlock *DestBB,
                        ArrayRef<SILValue> Args)
     : InstructionBase(Loc), DestBB(this, DestBB),
diff --git a/lib/SIL/SILLocation.cpp b/lib/SIL/SILLocation.cpp
index 1024b27..ac09dde5 100644
--- a/lib/SIL/SILLocation.cpp
+++ b/lib/SIL/SILLocation.cpp
@@ -64,12 +64,7 @@
   if (isSILFile())
     return Loc.SILFileLoc;
 
-  if (isAutoGenerated())
-    return SourceLoc();
-
   if (auto *expr = Loc.ASTNode.Primary.dyn_cast<Expr*>()) {
-    if (isa<CallExpr>(expr))
-      return expr->getEndLoc();
     // Code that has an autoclosure as location should not show up in
     // the line table (rdar://problem/14627460). Note also that the
     // closure function still has a valid DW_AT_decl_line.  Depending
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index aac1ced..2b41a69 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -240,8 +240,8 @@
   assert(!type->isNoEscape() && "Function decls always have escaping types.");
   if (auto fn = lookUpFunction(name)) {
     assert(fn->getLoweredFunctionType() == type);
-    assert(fn->getLinkage() == linkage ||
-           stripExternalFromLinkage(fn->getLinkage()) == linkage);
+    assert(stripExternalFromLinkage(fn->getLinkage()) ==
+           stripExternalFromLinkage(linkage));
     return fn;
   }
 
@@ -280,6 +280,32 @@
           PInfo.isGuaranteed() || PInfo.isIndirectMutating();
 }
 
+static void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
+                                  SILModule &M) {
+  for (auto *A : Attrs.getAttributes<SemanticsAttr>())
+    F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
+
+  // Propagate @_specialize.
+  for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
+    auto *SA = cast<SpecializeAttr>(A);
+    auto kind = SA->getSpecializationKind() ==
+                        SpecializeAttr::SpecializationKind::Full
+                    ? SILSpecializeAttr::SpecializationKind::Full
+                    : SILSpecializeAttr::SpecializationKind::Partial;
+    F->addSpecializeAttr(SILSpecializeAttr::create(
+        M, SA->getRequirements(), SA->isExported(), kind));
+  }
+
+  if (auto *OA = Attrs.getAttribute<OptimizeAttr>()) {
+    F->setOptimizationMode(OA->getMode());
+  }
+
+  // @_silgen_name and @_cdecl functions may be called from C code somewhere.
+  if (Attrs.hasAttribute<SILGenNameAttr>() ||
+      Attrs.hasAttribute<CDeclAttr>())
+    F->setHasCReferences(true);
+}
+
 SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
                                             SILDeclRef constant,
                                             ForDefinition_t forDefinition,
@@ -334,26 +360,12 @@
     if (constant.isForeign && decl->hasClangNode())
       F->setClangNodeOwner(decl);
 
-    // Propagate @_semantics.
-    auto Attrs = decl->getAttrs();
-    for (auto *A : Attrs.getAttributes<SemanticsAttr>())
-      F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
-
-    // Propagate @_specialize.
-    for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
-      auto *SA = cast<SpecializeAttr>(A);
-      auto kind = SA->getSpecializationKind() ==
-                          SpecializeAttr::SpecializationKind::Full
-                      ? SILSpecializeAttr::SpecializationKind::Full
-                      : SILSpecializeAttr::SpecializationKind::Partial;
-      F->addSpecializeAttr(SILSpecializeAttr::create(
-          *this, SA->getRequirements(), SA->isExported(), kind));
+    if (auto *FDecl = dyn_cast<FuncDecl>(decl)) {
+      if (auto *StorageDecl = FDecl->getAccessorStorageDecl())
+        // Add attributes for e.g. computed properties.
+        addFunctionAttributes(F, StorageDecl->getAttrs(), *this);
     }
-
-    // @_silgen_name and @_cdecl functions may be called from C code somewhere.
-    if (Attrs.hasAttribute<SILGenNameAttr>() ||
-        Attrs.hasAttribute<CDeclAttr>())
-      F->setHasCReferences(true);
+    addFunctionAttributes(F, decl->getAttrs(), *this);
   }
 
   // If this function has a self parameter, make sure that it has a +0 calling
@@ -513,8 +525,7 @@
   // compilation, simply convert it into an external declaration,
   // so that a compiled version from the shared library is used.
   if (F->isDefinition() &&
-      F->getModule().getOptions().Optimization <
-          SILOptions::SILOptMode::Optimize) {
+      !F->getModule().getOptions().shouldOptimize()) {
     F->convertToDeclaration();
   }
   if (F->isExternalDeclaration())
@@ -769,8 +780,7 @@
 
 /// Returns true if it is the optimized OnoneSupport module.
 bool SILModule::isOptimizedOnoneSupportModule() const {
-  return getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
-         isOnoneSupportModule();
+  return getOptions().shouldOptimize() && isOnoneSupportModule();
 }
 
 void SILModule::setSerializeSILAction(SILModule::ActionCallback Action) {
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 8372dce..cde8e70 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -448,6 +448,7 @@
 NO_OPERAND_INST(StrongRetainUnowned)
 NO_OPERAND_INST(UnownedRetain)
 NO_OPERAND_INST(Unreachable)
+NO_OPERAND_INST(Unwind)
 #undef NO_OPERAND_INST
 
 /// Instructions whose arguments are always compatible with one convention.
@@ -478,6 +479,7 @@
 CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, UnownedRelease)
 CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, InitExistentialRef)
 CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, EndLifetime)
+CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, AbortApply)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, AddressToPointer)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, BeginAccess)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, BeginUnpairedAccess)
@@ -490,6 +492,7 @@
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, DeinitExistentialAddr)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, DestroyAddr)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndAccess)
+CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndApply)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndUnpairedAccess)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, IndexAddr)
 CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, IndexRawPointer)
@@ -1088,6 +1091,11 @@
 }
 
 OwnershipUseCheckerResult
+OwnershipCompatibilityUseChecker::visitBeginApplyInst(BeginApplyInst *I) {
+  return visitFullApply(I);
+}
+
+OwnershipUseCheckerResult
 OwnershipCompatibilityUseChecker::visitApplyInst(ApplyInst *I) {
   return visitFullApply(I);
 }
@@ -1109,6 +1117,35 @@
 }
 
 OwnershipUseCheckerResult
+OwnershipCompatibilityUseChecker::visitYieldInst(YieldInst *I) {
+  // Indirect return arguments are address types.
+  if (isAddressOrTrivialType())
+    return {compatibleWithOwnership(ValueOwnershipKind::Trivial),
+            UseLifetimeConstraint::MustBeLive};
+
+  auto fnType = I->getFunction()->getLoweredFunctionType();
+  auto yieldInfo = fnType->getYields()[getOperandIndex()];
+  switch (yieldInfo.getConvention()) {
+  case ParameterConvention::Indirect_In:
+  case ParameterConvention::Direct_Owned:
+    return visitApplyParameter(ValueOwnershipKind::Owned,
+                               UseLifetimeConstraint::MustBeInvalidated);
+  case ParameterConvention::Indirect_In_Constant:
+  case ParameterConvention::Direct_Unowned:
+    // We accept unowned, owned, and guaranteed in unowned positions.
+    return {true, UseLifetimeConstraint::MustBeLive};
+  case ParameterConvention::Indirect_In_Guaranteed:
+  case ParameterConvention::Direct_Guaranteed:
+    return visitApplyParameter(ValueOwnershipKind::Guaranteed,
+                               UseLifetimeConstraint::MustBeLive);
+  // The following conventions should take address types.
+  case ParameterConvention::Indirect_Inout:
+  case ParameterConvention::Indirect_InoutAliasable:
+    llvm_unreachable("Unexpected non-trivial parameter convention.");
+  }
+}
+
+OwnershipUseCheckerResult
 OwnershipCompatibilityUseChecker::visitAssignInst(AssignInst *I) {
   if (getValue() == I->getSrc()) {
     if (isAddressOrTrivialType()) {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index a4dacb1..8a25896 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -351,7 +351,7 @@
     break;
   }
 
-  auto uncurryLevel = getUncurryLevel();
+  auto uncurryLevel = getParameterListCount() - 1;
   if (uncurryLevel != 0)
     OS << (isDot ? '.' : '!')  << uncurryLevel;
 
@@ -1073,9 +1073,8 @@
     *this << '>';
   }
 
-  void visitApplyInst(ApplyInst *AI) {
-    if (AI->isNonThrowing())
-      *this << "[nothrow] ";
+  template <class Inst>
+  void visitApplyInstBase(Inst *AI) {
     *this << Ctx.getID(AI->getCallee());
     printSubstitutions(AI->getSubstitutions());
     *this << '(';
@@ -1085,14 +1084,20 @@
     *this << ") : " << AI->getCallee()->getType();
   }
 
+  void visitApplyInst(ApplyInst *AI) {
+    if (AI->isNonThrowing())
+      *this << "[nothrow] ";
+    visitApplyInstBase(AI);
+  }
+
+  void visitBeginApplyInst(BeginApplyInst *AI) {
+    if (AI->isNonThrowing())
+      *this << "[nothrow] ";
+    visitApplyInstBase(AI);
+  }
+
   void visitTryApplyInst(TryApplyInst *AI) {
-    *this << Ctx.getID(AI->getCallee());
-    printSubstitutions(AI->getSubstitutions());
-    *this << '(';
-    interleave(AI->getArguments(),
-               [&](const SILValue &arg) { *this << Ctx.getID(arg); },
-               [&] { *this << ", "; });
-    *this << ") : " << AI->getCallee()->getType();
+    visitApplyInstBase(AI);
     *this << ", normal " << Ctx.getID(AI->getNormalBB());
     *this << ", error " << Ctx.getID(AI->getErrorBB());
   }
@@ -1115,13 +1120,15 @@
     case ParameterConvention::Indirect_InoutAliasable:
       llvm_unreachable("unexpected callee convention!");
     }
-    *this << Ctx.getID(CI->getCallee());
-    printSubstitutions(CI->getSubstitutions());
-    *this << '(';
-    interleave(CI->getArguments(),
-               [&](const SILValue &arg) { *this << Ctx.getID(arg); },
-               [&] { *this << ", "; });
-    *this << ") : " << CI->getCallee()->getType();
+    visitApplyInstBase(CI);
+  }
+
+  void visitAbortApplyInst(AbortApplyInst *AI) {
+    *this << Ctx.getID(AI->getOperand());
+  }
+
+  void visitEndApplyInst(EndApplyInst *AI) {
+    *this << Ctx.getID(AI->getOperand());
   }
 
   void visitFunctionRefInst(FunctionRefInst *FRI) {
@@ -1854,6 +1861,21 @@
     *this << getIDAndType(TI->getOperand());
   }
 
+  void visitUnwindInst(UnwindInst *UI) {
+    // no operands
+  }
+
+  void visitYieldInst(YieldInst *YI) {
+    auto values = YI->getYieldedValues();
+    if (values.size() != 1) *this << '(';
+    interleave(values,
+               [&](SILValue value) { *this << getIDAndType(value); },
+               [&] { *this << ", "; });
+    if (values.size() != 1) *this << ')';
+    *this << ", resume " << Ctx.getID(YI->getResumeBB())
+          << ", unwind " << Ctx.getID(YI->getUnwindBB());
+  }
+
   void visitSwitchValueInst(SwitchValueInst *SII) {
     *this << getIDAndType(SII->getOperand());
     for (unsigned i = 0, e = SII->getNumCases(); i < e; ++i) {
@@ -2230,6 +2252,13 @@
     case InlineDefault: break;
   }
 
+  switch (getOptimizationMode()) {
+    case OptimizationMode::NoOptimization: OS << "[Onone] "; break;
+    case OptimizationMode::ForSpeed: OS << "[Ospeed] "; break;
+    case OptimizationMode::ForSize: OS << "[Osize] "; break;
+    default: break;
+  }
+
   if (getEffectsKind() == EffectsKind::ReadOnly)
     OS << "[readonly] ";
   else if (getEffectsKind() == EffectsKind::ReadNone)
@@ -2731,7 +2760,22 @@
     }
     OS << '\n';
   }
-  
+
+  for (auto conditionalConformance : getConditionalConformances()) {
+    // conditional_conformance (TypeName: Protocol):
+    // <conformance>
+    OS << "  conditional_conformance (";
+    conditionalConformance.Requirement.print(OS, Options);
+    OS << ": " << conditionalConformance.Conformance.getRequirement()->getName()
+       << "): ";
+    if (conditionalConformance.Conformance.isConcrete())
+      conditionalConformance.Conformance.getConcrete()->printName(OS, Options);
+    else
+      OS << "dependent";
+
+    OS << '\n';
+  }
+
   OS << "}\n\n";
 }
 
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index 87ad018..c99d242 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -71,6 +71,10 @@
   return getPrimitiveType(CanType(optType), type.getCategory());
 }
 
+SILType SILType::getSILTokenType(const ASTContext &C) {
+  return getPrimitiveObjectType(C.TheSILTokenType);
+}
+
 bool SILType::isTrivial(SILModule &M) const {
   return M.getTypeLowering(*this).isTrivial();
 }
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 7252575..15afdf3 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -671,9 +671,24 @@
   /// Check that the types of this value producer are all legal in the function
   /// context in which it exists.
   void checkLegalType(SILFunction *F, ValueBase *value, SILInstruction *I) {
-    if (SILType type = value->getType()) {
-      checkLegalType(F, type, I);
+    SILType type = value->getType();
+    if (type.is<SILTokenType>()) {
+      require(isLegalSILTokenProducer(value),
+              "SIL tokens can only be produced as the results of specific "
+              "instructions");
+      return;
     }
+
+    checkLegalType(F, type, I);
+  }
+
+  static bool isLegalSILTokenProducer(SILValue value) {
+    if (auto beginApply = dyn_cast<BeginApplyResult>(value))
+      return beginApply->isTokenResult();
+
+    // Add more token cases here as they arise.
+
+    return false;
   }
 
   /// Check that the given type is a legal SIL value type.
@@ -918,9 +933,9 @@
     // Check that the arguments and result match.
     SILFunctionConventions substConv(substTy, F.getModule());
     //require(site.getArguments().size() == substTy->getNumSILArguments(),
-    require(site.getNumCallArguments() == substConv.getNumSILArguments(),
+    require(site.getNumArguments() == substConv.getNumSILArguments(),
             "apply doesn't have right number of arguments for function");
-    for (size_t i = 0, size = site.getNumCallArguments(); i < size; ++i) {
+    for (size_t i = 0, size = site.getNumArguments(); i < size; ++i) {
       requireSameType(site.getArguments()[i]->getType(),
                       substConv.getSILArgumentType(i),
                       "operand of 'apply' doesn't match function input type");
@@ -941,6 +956,9 @@
               "apply instruction cannot call function with error result");
     }
 
+    require(!calleeConv.funcTy->isCoroutine(),
+            "cannot call coroutine with normal apply");
+
     // Check that if the apply is of a noreturn callee, make sure that an
     // unreachable is the next instruction.
     if (AI->getModule().getStage() == SILStage::Raw ||
@@ -955,6 +973,9 @@
 
     SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
 
+    require(!calleeConv.funcTy->isCoroutine(),
+            "cannot call coroutine with normal apply");
+
     auto normalBB = AI->getNormalBB();
     require(normalBB->args_size() == 1,
             "normal destination of try_apply must take one argument");
@@ -974,6 +995,43 @@
                     "of error result type");
   }
 
+  void checkBeginApplyInst(BeginApplyInst *AI) {
+    checkFullApplySite(AI);
+
+    SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
+    auto yieldResults = AI->getYieldedValues();
+    auto yields = calleeConv.getYields();
+    require(yields.size() == yieldResults.size(),
+            "length mismatch in callee yields vs. begin_apply results");
+    for (auto i : indices(yields)) {
+      require(yieldResults[i]->getType() == calleeConv.getSILType(yields[i]),
+              "callee yield type does not match begin_apply result type");
+    }
+
+    if (AI->isNonThrowing()) {
+      require(calleeConv.funcTy->hasErrorResult(),
+              "nothrow flag used for callee without error result");
+    } else {
+      require(!calleeConv.funcTy->hasErrorResult(),
+              "begin_apply instruction cannot call function with error result");
+    }
+
+    require(calleeConv.funcTy->getCoroutineKind() == SILCoroutineKind::YieldOnce,
+            "must call yield_once coroutine with begin_apply");
+  }
+
+  void checkAbortApplyInst(AbortApplyInst *AI) {
+    require(isa<BeginApplyResult>(AI->getOperand()) &&
+            cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
+            "operand of abort_apply must be a begin_apply");
+  }
+
+  void checkEndApplyInst(EndApplyInst *AI) {
+    require(isa<BeginApplyResult>(AI->getOperand()) &&
+            cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
+            "operand of end_apply must be a begin_apply");
+  }
+
   void verifyLLVMIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID) {
     // Certain llvm intrinsic require constant values as their operands.
     // Consequently, these must not be phi nodes (aka. basic block arguments).
@@ -2164,6 +2222,8 @@
     auto constantInfo = F.getModule().Types.getConstantInfo(method);
     auto methodTy = constantInfo.SILFnType;
 
+    assert(!methodTy->isCoroutine());
+
     // Map interface types to archetypes.
     if (auto *env = constantInfo.GenericEnv) {
       auto subs = env->getForwardingSubstitutions();
@@ -2196,8 +2256,10 @@
 
     auto fnTy = SILFunctionType::get(nullptr,
                                      methodTy->getExtInfo(),
+                                     methodTy->getCoroutineKind(),
                                      methodTy->getCalleeConvention(),
                                      dynParams,
+                                     methodTy->getYields(),
                                      dynResults,
                                      methodTy->getOptionalErrorResult(),
                                      F.getASTContext());
@@ -3309,6 +3371,35 @@
             "throw operand type does not match error result type of function");
   }
   
+  void checkUnwindInst(UnwindInst *UI) {
+    require(F.getLoweredFunctionType()->isCoroutine(),
+            "unwind in non-coroutine function");
+  }
+
+  void checkYieldInst(YieldInst *YI) {
+    CanSILFunctionType fnType = F.getLoweredFunctionType();
+    require(fnType->isCoroutine(),
+            "yield in non-coroutine function");
+
+    auto yieldedValues = YI->getYieldedValues();
+    auto yieldInfos = fnType->getYields();
+    require(yieldedValues.size() == yieldInfos.size(),
+            "wrong number of yielded values for function");
+    for (auto i : indices(yieldedValues)) {
+      SILType yieldType =
+        F.mapTypeIntoContext(fnConv.getSILType(yieldInfos[i]));
+      require(yieldedValues[i]->getType() == yieldType,
+              "yielded value does not match yield type of coroutine");
+    }
+
+    // We require the resume and unwind destinations to be unique in order
+    // to prevent either edge from becoming critical.
+    require(YI->getResumeBB()->getSinglePredecessorBlock(),
+            "resume dest of 'yield' must be uniquely used");
+    require(YI->getUnwindBB()->getSinglePredecessorBlock(),
+            "unwind dest of 'yield' must be uniquely used");
+  }
+
   void checkSelectEnumCases(SelectEnumInstBase *I) {
     EnumDecl *eDecl = I->getEnumOperand()->getType().getEnumOrBoundGenericEnum();
     require(eDecl, "select_enum operand must be an enum");
@@ -4147,9 +4238,21 @@
   /// - accesses must be uniquely ended
   /// - flow-sensitive states must be equivalent on all paths into a block
   void verifyFlowSensitiveRules(SILFunction *F) {
+    enum CFGState {
+      /// No special rules are in play.
+      Normal,
+      /// We've followed the resume edge of a yield in a yield_once coroutine.
+      YieldOnceResume,
+      /// We've followed the unwind edge of a yield.
+      YieldUnwind
+    };
     struct BBState {
       std::vector<SingleValueInstruction*> Stack;
-      std::set<BeginAccessInst*> Accesses;
+
+      /// Contents: BeginAccessInst*, BeginApplyInst*.
+      std::set<SILInstruction*> ActiveOps;
+
+      CFGState CFG = Normal;
     };
 
     // Do a breath-first search through the basic blocks.
@@ -4176,25 +4279,47 @@
                   "stack dealloc does not match most recent stack alloc");
           state.Stack.pop_back();
 
-        } else if (auto access = dyn_cast<BeginAccessInst>(&i)) {
-          bool notAlreadyPresent = state.Accesses.insert(access).second;
+        } else if (isa<BeginAccessInst>(i) || isa<BeginApplyInst>(i)) {
+          bool notAlreadyPresent = state.ActiveOps.insert(&i).second;
           require(notAlreadyPresent,
-                  "access was not ended before re-beginning it");
+                  "operation was not ended before re-beginning it");
 
-        } else if (auto endAccess = dyn_cast<EndAccessInst>(&i)) {
-          // We don't call getBeginAccess() because this isn't the right
-          // place to assert on malformed SIL.
-          if (auto access = dyn_cast<BeginAccessInst>(endAccess->getOperand())){
-            bool present = state.Accesses.erase(access);
-            require(present, "access has already been ended");
+        } else if (isa<EndAccessInst>(i) || isa<AbortApplyInst>(i) ||
+                   isa<EndApplyInst>(i)) {
+          if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
+            bool present = state.ActiveOps.erase(beginOp);
+            require(present, "operation has already been ended");
           }
 
         } else if (auto term = dyn_cast<TermInst>(&i)) {
           if (term->isFunctionExiting()) {
             require(state.Stack.empty(),
                     "return with stack allocs that haven't been deallocated");
-            require(state.Accesses.empty(),
-                    "return with accesses that haven't been ended");
+            require(state.ActiveOps.empty(),
+                    "return with operations still active");
+
+            if (isa<UnwindInst>(term)) {
+              require(state.CFG == YieldUnwind,
+                      "encountered 'unwind' when not on unwind path");
+            } else {
+              require(state.CFG != YieldUnwind,
+                      "encountered 'return' or 'throw' when on unwind path");
+              if (isa<ReturnInst>(term) &&
+                  F->getLoweredFunctionType()->getCoroutineKind() ==
+                    SILCoroutineKind::YieldOnce &&
+                  F->getModule().getStage() != SILStage::Raw) {
+                require(state.CFG == YieldOnceResume,
+                        "encountered 'return' before yielding a value in "
+                        "yield_once coroutine");
+              }
+            }
+          }
+
+          if (isa<YieldInst>(term)) {
+            require(state.CFG != YieldOnceResume,
+                    "encountered multiple 'yield's along single path");
+            require(state.CFG == Normal,
+                    "encountered 'yield' on abnormal CFG path");
           }
 
           auto successors = term->getSuccessors();
@@ -4215,9 +4340,30 @@
             // worklist and continue.
             if (insertResult.second) {
               Worklist.push_back(succBB);
+
+              // If we're following a 'yield', update the CFG state:
+              if (isa<YieldInst>(term)) {
+                // Enforce that the unwind logic is segregated in all stages.
+                if (i == 1) {
+                  insertResult.first->second.CFG = YieldUnwind;
+
+                // We check the yield_once rule in the mandatory analyses,
+                // so we can't assert it yet in the raw stage.
+                } else if (F->getLoweredFunctionType()->getCoroutineKind()
+                             == SILCoroutineKind::YieldOnce && 
+                           F->getModule().getStage() != SILStage::Raw) {
+                  insertResult.first->second.CFG = YieldOnceResume;
+                }
+              }
+
               continue;
             }
 
+            // This rule is checked elsewhere, but we'd want to assert it
+            // here anyway.
+            require(!isa<YieldInst>(term),
+                    "successor of 'yield' should not be encountered twice");
+
             // Check that the stack height is consistent coming from all entry
             // points into this BB. We only care about consistency if there is
             // a possible return from this function along the path starting at
@@ -4231,8 +4377,10 @@
             const auto &foundState = insertResult.first->second;
             require(state.Stack == foundState.Stack || isUnreachable(),
                     "inconsistent stack heights entering basic block");
-            require(state.Accesses == foundState.Accesses || isUnreachable(),
-                    "inconsistent access sets entering basic block");
+            require(state.ActiveOps == foundState.ActiveOps || isUnreachable(),
+                    "inconsistent active-operations sets entering basic block");
+            require(state.CFG == foundState.CFG,
+                    "inconsistent coroutine states entering basic block");
           }
         }
       }
diff --git a/lib/SIL/SILWitnessTable.cpp b/lib/SIL/SILWitnessTable.cpp
index 4e0728e..a6f31d4 100644
--- a/lib/SIL/SILWitnessTable.cpp
+++ b/lib/SIL/SILWitnessTable.cpp
@@ -43,11 +43,11 @@
   Mod.witnessTables.push_back(this);
 }
 
-SILWitnessTable *
-SILWitnessTable::create(SILModule &M, SILLinkage Linkage,
-                        IsSerialized_t Serialized,
-                        NormalProtocolConformance *Conformance,
-                        ArrayRef<SILWitnessTable::Entry> entries) {
+SILWitnessTable *SILWitnessTable::create(
+    SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+    NormalProtocolConformance *Conformance,
+    ArrayRef<SILWitnessTable::Entry> entries,
+    ArrayRef<ConditionalConformance> conditionalConformances) {
   assert(Conformance && "Cannot create a witness table for a null "
          "conformance.");
 
@@ -56,8 +56,9 @@
 
   // Allocate the witness table and initialize it.
   void *buf = M.allocate(sizeof(SILWitnessTable), alignof(SILWitnessTable));
-  SILWitnessTable *wt = ::new (buf) SILWitnessTable(M, Linkage, Serialized,
-                                           Name.str(), Conformance, entries);
+  SILWitnessTable *wt = ::new (buf)
+      SILWitnessTable(M, Linkage, Serialized, Name.str(), Conformance, entries,
+                      conditionalConformances);
 
   wt->addWitnessTable();
 
@@ -86,20 +87,19 @@
   return wt;
 }
 
-SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage,
-                                 IsSerialized_t Serialized, StringRef N,
-                                 NormalProtocolConformance *Conformance,
-                                 ArrayRef<Entry> entries)
-  : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
-    IsDeclaration(true), Serialized(false) {
-  convertToDefinition(entries, Serialized);
+SILWitnessTable::SILWitnessTable(
+    SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized, StringRef N,
+    NormalProtocolConformance *Conformance, ArrayRef<Entry> entries,
+    ArrayRef<ConditionalConformance> conditionalConformances)
+    : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
+      ConditionalConformances(), IsDeclaration(true), Serialized(false) {
+  convertToDefinition(entries, conditionalConformances, Serialized);
 }
 
 SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage, StringRef N,
                                  NormalProtocolConformance *Conformance)
-  : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
-    IsDeclaration(true), Serialized(false)
-{}
+    : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
+      ConditionalConformances(), IsDeclaration(true), Serialized(false) {}
 
 SILWitnessTable::~SILWitnessTable() {
   if (isDeclaration())
@@ -127,14 +127,17 @@
   return Serialized ? IsSerialized : IsNotSerialized;
 }
 
-void SILWitnessTable::convertToDefinition(ArrayRef<Entry> entries,
-                                          IsSerialized_t isSerialized) {
+void SILWitnessTable::convertToDefinition(
+    ArrayRef<Entry> entries,
+    ArrayRef<ConditionalConformance> conditionalConformances,
+    IsSerialized_t isSerialized) {
   assert(isDeclaration() && "Definitions should never call this method.");
   IsDeclaration = false;
   assert(isSerialized != IsSerializable);
   Serialized = (isSerialized == IsSerialized);
 
   Entries = Mod.allocateCopy(entries);
+  ConditionalConformances = Mod.allocateCopy(conditionalConformances);
 
   // Bump the reference count of witness functions referenced by this table.
   for (auto entry : getEntries()) {
@@ -174,3 +177,23 @@
   auto typeIsPublic = nominal->getEffectiveAccess() >= AccessLevel::Public;
   return nominal->hasFixedLayout() && protocolIsPublic && typeIsPublic;
 }
+
+bool SILWitnessTable::enumerateWitnessTableConditionalConformances(
+    const ProtocolConformance *conformance,
+    llvm::function_ref<bool(unsigned, CanType, ProtocolDecl *)> fn) {
+  unsigned conformanceIndex = 0;
+  for (auto req : conformance->getConditionalRequirements()) {
+    if (req.getKind() != RequirementKind::Conformance)
+      continue;
+
+    auto proto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
+
+    if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto)) {
+      if (fn(conformanceIndex, req.getFirstType()->getCanonicalType(), proto))
+        return true;
+
+      conformanceIndex++;
+    }
+  }
+  return false;
+}
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index da1b89c..83c83f2 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -211,6 +211,7 @@
     IMPL(BuiltinUnknownObject, Reference)
     IMPL(BuiltinUnsafeValueBuffer, AddressOnly)
     IMPL(BuiltinVector, Trivial)
+    IMPL(SILToken, Trivial)
     IMPL(Class, Reference)
     IMPL(BoundGenericClass, Reference)
     IMPL(AnyMetatype, Trivial)
@@ -2107,9 +2108,9 @@
   if (genericSig && genericSig->areAllParamsConcrete())
     genericSig = nullptr;
 
-  return SILFunctionType::get(genericSig, extInfo,
+  return SILFunctionType::get(genericSig, extInfo, SILCoroutineKind::None,
                               /*callee*/ ParameterConvention::Direct_Unowned,
-                              params, results, None, ctx,
+                              params, {}, results, None, ctx,
                               witnessMethodConformance);
 }
 
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index 0d56fc9..b6e7982 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -262,6 +262,11 @@
   return Result->getOwnershipKind();
 }
 
+ValueOwnershipKind ValueOwnershipKindClassifier::visitBeginApplyResult(
+    BeginApplyResult *Result) {
+  return Result->getOwnershipKind();
+}
+
 ValueOwnershipKind ValueOwnershipKindClassifier::visitSILFunctionArgument(
     SILFunctionArgument *Arg) {
   return Arg->getOwnershipKind();
diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp
index 5661f17..7226ee8 100644
--- a/lib/SILGen/ArgumentSource.cpp
+++ b/lib/SILGen/ArgumentSource.cpp
@@ -21,25 +21,6 @@
 using namespace swift;
 using namespace Lowering;
 
-RValue &ArgumentSource::forceAndPeekRValue(SILGenFunction &SGF) & {
-  if (isRValue()) {
-    return peekRValue();
-  }
-
-  // Extract an r-value.
-  SILLocation loc = getLocation();
-  RValue value = std::move(*this).getAsRValue(SGF);
-
-  // Destroy the current state.
-  Storage.destruct(StoredKind);
-
-  // Emplace the r-value back into the source.
-  StoredKind = Kind::RValue;
-  Storage.emplaceAggregate<RValueStorage>(StoredKind, std::move(value), loc);
-
-  return peekRValue();
-}
-
 RValue &ArgumentSource::peekRValue() & {
   assert(isRValue() && "Undefined behavior to call this method without the "
          "ArgumentSource actually being an RValue");
@@ -55,7 +36,6 @@
   case Kind::Tuple:
     llvm_unreachable("cannot rewrite type of tuple");
   case Kind::RValue:
-  case Kind::DelayedBorrowedRValue:
     Storage.get<RValueStorage>(StoredKind).Value.rewriteType(newType);
     return;
   case Kind::Expr:
@@ -89,7 +69,6 @@
   case Kind::Invalid:
     llvm_unreachable("argument source is invalid");
   case Kind::RValue:
-  case Kind::DelayedBorrowedRValue:
   case Kind::LValue:
     return false;
   case Kind::Expr:
@@ -138,9 +117,6 @@
     llvm_unreachable("argument source is invalid");
   case Kind::LValue:
     llvm_unreachable("cannot get l-value as r-value");
-  case Kind::DelayedBorrowedRValue:
-    return std::move(*this).asKnownRValue(SGF).borrow(SGF,
-                                                      getKnownRValueLocation());
   case Kind::RValue:
     return std::move(*this).asKnownRValue(SGF);
   case Kind::Expr:
@@ -195,15 +171,6 @@
     return SGF.emitAddressOfLValue(loc, std::move(*this).asKnownLValue(),
                                    AccessKind::ReadWrite);
   }
-  case Kind::DelayedBorrowedRValue: {
-    assert(!C.getEmitInto() &&
-           "Can not put a delayed borrowed rvalue into an initialization");
-    auto loc = getKnownRValueLocation();
-    return std::move(*this)
-        .asKnownRValue(SGF)
-        .getAsSingleValue(SGF, loc)
-        .borrow(SGF, loc);
-  }
   case Kind::RValue: {
     auto loc = getKnownRValueLocation();
     if (auto init = C.getEmitInto()) {
@@ -250,9 +217,6 @@
     llvm_unreachable("argument source is invalid");
   case Kind::LValue:
     llvm_unreachable("cannot get converted l-value");
-  case Kind::DelayedBorrowedRValue:
-    // TODO: We probably can, but we would need to introduce a copy.
-    llvm_unreachable("cannot get converted borrowed r-value");
   case Kind::RValue:
   case Kind::Expr:
   case Kind::Tuple:
@@ -270,8 +234,6 @@
     llvm_unreachable("argument source is invalid");
   case Kind::LValue:
     llvm_unreachable("cannot forward an l-value");
-  case Kind::DelayedBorrowedRValue:
-    llvm_unreachable("cannot forward a delayed borrowed r-value");
   case Kind::RValue: {
     auto loc = getKnownRValueLocation();
     std::move(*this).asKnownRValue(SGF).forwardInto(SGF, loc, dest);
@@ -299,26 +261,12 @@
   Storage.emplaceAggregate<RValueStorage>(StoredKind, std::move(rv), loc);
 }
 
-ArgumentSource ArgumentSource::delayedBorrow(SILGenFunction &SGF) const & {
-  assert(isRValue() && "Can only perform a delayed borrow on an rvalue");
-  // We are doing something evil here since we know that we are going to perform
-  // a borrow.
-  //
-  // Once uncurrying is removed from the compiler, we will no longer need to
-  // perform delayed borrows and this evilness can be expunged.
-  const RValue &rv = asKnownRValue();
-  return ArgumentSource(getKnownRValueLocation(),
-                        RValue(&SGF, rv.values, rv.type),
-                        Kind::DelayedBorrowedRValue);
-}
-
 ArgumentSource ArgumentSource::borrow(SILGenFunction &SGF) const & {
   switch (StoredKind) {
   case Kind::Invalid:
     llvm_unreachable("argument source is invalid");
   case Kind::LValue:
     llvm_unreachable("cannot borrow an l-value");
-  case Kind::DelayedBorrowedRValue:
   case Kind::RValue: {
     auto loc = getKnownRValueLocation();
     return ArgumentSource(loc, asKnownRValue().borrow(SGF, loc));
@@ -449,7 +397,6 @@
     return;
   }
   case Kind::RValue:
-  case Kind::DelayedBorrowedRValue:
     out << "RValue\n";
     Storage.get<RValueStorage>(StoredKind).Value.dump(out, indent + 2);
     return;
diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h
index 63f4417..036a46e 100644
--- a/lib/SILGen/ArgumentSource.h
+++ b/lib/SILGen/ArgumentSource.h
@@ -52,8 +52,6 @@
   enum class Kind : unsigned char {
     Invalid,
     RValue,
-    // An RValue that will be borrowed when emitted.
-    DelayedBorrowedRValue,
     LValue,
     Expr,
     Tuple,
@@ -91,7 +89,6 @@
     switch (kind) {
     case Kind::Invalid: return StorageMembers::indexOf<void>();
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return StorageMembers::indexOf<RValueStorage>();
     case Kind::LValue: return StorageMembers::indexOf<LValueStorage>();
     case Kind::Expr: return StorageMembers::indexOf<Expr*>();
@@ -147,7 +144,6 @@
     case Kind::Invalid:
       return false;
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return !asKnownRValue().isNull();
     case Kind::LValue:
       return asKnownLValue().isValid();
@@ -164,7 +160,6 @@
     case Kind::Invalid:
       llvm_unreachable("argument source is invalid");
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return asKnownRValue().getType();
     case Kind::LValue:
       return CanInOutType::get(asKnownLValue().getSubstFormalType());
@@ -183,7 +178,6 @@
     case Kind::Invalid:
       llvm_unreachable("argument source is invalid");
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return asKnownRValue().getType();
     case Kind::LValue:
       return asKnownLValue().getSubstFormalType();
@@ -201,7 +195,6 @@
     switch (StoredKind) {
     case Kind::Invalid: llvm_unreachable("argument source is invalid");
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return false;
     case Kind::LValue: return true;
     case Kind::Expr: return asKnownExpr()->isSemanticallyInOutExpr();
@@ -215,7 +208,6 @@
     case Kind::Invalid:
       llvm_unreachable("argument source is invalid");
     case Kind::RValue:
-    case Kind::DelayedBorrowedRValue:
       return getKnownRValueLocation();
     case Kind::LValue:
       return getKnownLValueLocation();
@@ -228,21 +220,13 @@
   }
 
   bool isExpr() const & { return StoredKind == Kind::Expr; }
-  bool isRValue() const & {
-    return StoredKind == Kind::RValue ||
-           StoredKind == Kind::DelayedBorrowedRValue;
-  }
+  bool isRValue() const & { return StoredKind == Kind::RValue; }
   bool isLValue() const & { return StoredKind == Kind::LValue; }
   bool isTuple() const & { return StoredKind == Kind::Tuple; }
 
   /// Given that this source is storing an RValue, extract and clear
   /// that value.
   RValue &&asKnownRValue(SILGenFunction &SGF) && {
-    if (isDelayedBorrowedRValue()) {
-      std::move(Storage.get<RValueStorage>(StoredKind).Value)
-          .borrow(SGF, getKnownRValueLocation());
-    }
-
     return std::move(Storage.get<RValueStorage>(StoredKind).Value);
   }
 
@@ -287,10 +271,6 @@
     return result;
   }
 
-  /// Force this source to become an r-value, then return an unmoved
-  /// handle to that r-value.
-  RValue &forceAndPeekRValue(SILGenFunction &SGF) &;
-
   /// Return an unowned handle to the r-value stored in this source. Undefined
   /// if this ArgumentSource is not an rvalue.
   RValue &peekRValue() &;
@@ -313,15 +293,6 @@
   /// return the ArgumentSource. Otherwise, assert.
   ArgumentSource borrow(SILGenFunction &SGF) const &;
 
-  /// If we have an rvalue, return an Argument Source that when the RValue is
-  /// retrieved, the RValue is always borrowed first.
-  ///
-  /// This allows us to specify when creating callees that a value must be
-  /// borrowed, but emit the actual borrow once the callee is evaluated later in
-  /// SILGenApply. Ideally, the callee would always eagerly borrow, but since we
-  /// still have uncurrying, we can not do that.
-  ArgumentSource delayedBorrow(SILGenFunction &SGF) const &;
-
   ManagedValue materialize(SILGenFunction &SGF) &&;
 
   /// Emit this value to memory so that it follows the abstraction
@@ -346,14 +317,6 @@
   /// Private helper constructor for delayed borrowed rvalues.
   ArgumentSource(SILLocation loc, RValue &&rv, Kind kind);
 
-  /// Returns true if this ArgumentSource stores a delayed borrowed RValue.
-  ///
-  /// This is private since we do not want users to be able to determine if the
-  /// given ArgumentSource is a normal RValue or a delayed borrow rvalue.
-  bool isDelayedBorrowedRValue() const & {
-    return StoredKind == Kind::DelayedBorrowedRValue;
-  }
-
   // Make the non-move accessors private to make it more difficult
   // to accidentally re-emit values.
   const RValue &asKnownRValue() const & {
diff --git a/lib/SILGen/Cleanup.cpp b/lib/SILGen/Cleanup.cpp
index 567e95a..bdaf095 100644
--- a/lib/SILGen/Cleanup.cpp
+++ b/lib/SILGen/Cleanup.cpp
@@ -138,7 +138,7 @@
 
   // Otherwise, create and emit a new block.
   auto *newBlock = SGF.createBasicBlock();
-  SavedInsertionPoint IPRAII(SGF, newBlock);
+  SILGenSavedInsertionPoint IPRAII(SGF, newBlock);
   emitBranchAndCleanups(dest, branchLoc, args);
   return newBlock;
 }
diff --git a/lib/SILGen/RValue.h b/lib/SILGen/RValue.h
index d7191d1..68fd72a 100644
--- a/lib/SILGen/RValue.h
+++ b/lib/SILGen/RValue.h
@@ -225,22 +225,6 @@
   /// Get the rvalue as a single unmanaged value, imploding tuples if necessary.
   /// The values must not require any cleanups.
   SILValue getUnmanagedSingleValue(SILGenFunction &SGF, SILLocation l) const &;
-  
-  /// Peek at the single scalar value backing this rvalue without consuming it.
-  /// The rvalue must not be of a tuple type.
-  SILValue peekScalarValue() const & {
-    assert(!isa<TupleType>(type) && "peekScalarValue of a tuple rvalue");
-    assert(values.size() == 1 && "exploded scalar value?!");
-    return values[0].getValue();
-  }
-
-  /// Peek at the single ManagedValue backing this rvalue without consuming it
-  /// and return true if the value is not at +1.
-  bool peekIsPlusZeroRValueOrTrivial() const & {
-    assert(!isa<TupleType>(type) && "peekScalarValue of a tuple rvalue");
-    assert(values.size() == 1 && "exploded scalar value?!");
-    return values[0].isPlusZeroRValueOrTrivial();
-  }
 
   ManagedValue getScalarValue() && {
     assert(!isa<TupleType>(type) && "getScalarValue of a tuple rvalue");
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index bb4e271..abc9989 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -432,8 +432,9 @@
   };
 
   CanSILFunctionType topLevelType = SILFunctionType::get(nullptr, extInfo,
+                                   SILCoroutineKind::None,
                                    ParameterConvention::Direct_Unowned,
-                                   params,
+                                   params, /*yields*/ {},
                                    SILResultInfo(Int32Ty,
                                                  ResultConvention::Unowned),
                                    None,
@@ -1323,8 +1324,8 @@
         SGF.B.emitBlock(returnBB);
 
         // Emit the rethrow block.
-        SavedInsertionPoint savedIP(SGF, rethrowBB,
-                                    FunctionSection::Postmatter);
+        SILGenSavedInsertionPoint savedIP(SGF, rethrowBB,
+                                          FunctionSection::Postmatter);
 
         // Log the error.
         SILValue error = rethrowBB->getArgument(0);
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 0c42dad..b64c803 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -181,11 +181,19 @@
   /// Get the function for a SILDeclRef, creating it if necessary.
   SILFunction *getFunction(SILDeclRef constant,
                            ForDefinition_t forDefinition);
-  
+
+  /// Get the function for a dispatch thunk, creating it if necessary.
+  SILFunction *getDispatchThunk(SILDeclRef constant,
+                                ForDefinition_t forDefinition);
+
+  /// Emit a native Swift class or protocol method dispatch thunk, used for
+  /// resilient method dispatch.
+  SILFunction *emitDispatchThunk(SILDeclRef constant);
+
   /// Get the dynamic dispatch thunk for a SILDeclRef.
   SILFunction *getDynamicThunk(SILDeclRef constant,
                                CanSILFunctionType constantTy);
-  
+
   /// Emit a vtable thunk for a derived method if its natural abstraction level
   /// diverges from the overridden base method. If no thunking is needed,
   /// returns a static reference to the derived method.
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 71395d6..445abfb 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -64,16 +64,6 @@
   llvm_unreachable("bad representation");
 }
 
-static CanType getDynamicMethodSelfType(SILGenFunction &SGF,
-                                        const ArgumentSource &proto,
-                                        ValueDecl *member) {
-  if (member->isInstanceMember()) {
-    return SGF.getASTContext().getAnyObjectType();
-  } else {
-    return proto.getSILSubstType(SGF).getSwiftRValueType();
-  }
-}
-
 /// Return the formal type for the partial-apply result type of a
 /// dynamic method invocation.
 static CanFunctionType
@@ -113,55 +103,16 @@
   return fnType;
 }
 
-/// Replace the 'self' parameter in the given type.
-static CanSILFunctionType
-replaceSelfTypeForDynamicLookup(ASTContext &ctx,
-                                CanSILFunctionType fnType,
-                                CanType newSelfType,
-                                SILDeclRef methodName) {
-  auto oldParams = fnType->getParameters();
-  SmallVector<SILParameterInfo, 4> newParams;
-  newParams.append(oldParams.begin(), oldParams.end() - 1);
-  newParams.push_back({newSelfType, oldParams.back().getConvention()});
-
-  // If the method returns Self, substitute AnyObject for the result type.
-  SmallVector<SILResultInfo, 4> newResults;
-  newResults.append(fnType->getResults().begin(), fnType->getResults().end());
-  if (auto fnDecl = dyn_cast<FuncDecl>(methodName.getDecl())) {
-    if (fnDecl->hasDynamicSelf()) {
-      auto anyObjectTy = ctx.getAnyObjectType();
-      for (auto &result : newResults) {
-        auto newResultTy
-          = result.getType()->replaceCovariantResultType(anyObjectTy, 0);
-        result = result.getWithType(newResultTy->getCanonicalType());
-      }
-    }
-  }
-
-  return SILFunctionType::get(nullptr, fnType->getExtInfo(),
-                              fnType->getCalleeConvention(), newParams,
-                              newResults, fnType->getOptionalErrorResult(), ctx,
-                              fnType->getWitnessMethodConformanceOrNone());
-}
-
 /// Retrieve the type to use for a method found via dynamic lookup.
-static CanSILFunctionType
-getDynamicMethodLoweredType(SILGenFunction &SGF, SILValue v,
-                            SILDeclRef methodName,
+static SILType
+getDynamicMethodLoweredType(SILModule &M,
+                            SILDeclRef constant,
                             CanAnyFunctionType substMemberTy) {
-  auto &ctx = SGF.getASTContext();
-  CanType selfTy = v->getType().getSwiftRValueType();
-  assert((!methodName.getDecl()->isInstanceMember() ||
-          selfTy->is<ArchetypeType>()) &&
-         "Dynamic lookup needs an archetype");
-
-  // Replace the 'self' parameter type in the method type with it.
+  assert(constant.isForeign);
   auto objcFormalTy = substMemberTy.withExtInfo(substMemberTy->getExtInfo()
              .withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod));
-
-  auto methodTy = SGF.SGM.M.Types
-    .getUncachedSILFunctionTypeForConstant(methodName, objcFormalTy);
-  return replaceSelfTypeForDynamicLookup(ctx, methodTy, selfTy, methodName);
+  return SILType::getPrimitiveObjectType(
+      M.Types.getUncachedSILFunctionTypeForConstant(constant, objcFormalTy));
 }
 
 /// Check if we can perform a dynamic dispatch on a super method call.
@@ -198,6 +149,9 @@
 }
 
 static SILValue getOriginalSelfValue(SILValue selfValue) {
+  if (auto *TTOI = dyn_cast<ThickToObjCMetatypeInst>(selfValue))
+    selfValue = TTOI->getOperand();
+
   if (auto *BBI = dyn_cast<BeginBorrowInst>(selfValue))
     selfValue = BBI->getOperand();
 
@@ -283,10 +237,6 @@
   /// *NOTE* This should never be non-null if IndirectValue is non-null.
   SILDeclRef Constant;
 
-  /// This field is set if we are calling to a SuperMethod or ClassMethod and
-  /// thus need to pass self to get the correct implementation.
-  Optional<ArgumentSource> SelfValue;
-
   /// The abstraction pattern of the callee.
   AbstractionPattern OrigFormalInterfaceType;
 
@@ -339,11 +289,10 @@
   {
   }
 
-  Callee(Kind methodKind, SILGenFunction &SGF,
-         Optional<ArgumentSource> &&selfValue, SILDeclRef methodName,
+  Callee(Kind methodKind, SILGenFunction &SGF, SILDeclRef methodName,
          AbstractionPattern origFormalType, CanAnyFunctionType substFormalType,
          SubstitutionList subs, SILLocation l)
-      : kind(methodKind), Constant(methodName), SelfValue(std::move(selfValue)),
+      : kind(methodKind), Constant(methodName),
         OrigFormalInterfaceType(origFormalType),
         SubstFormalInterfaceType(
             getSubstFormalInterfaceType(substFormalType, subs)),
@@ -368,23 +317,23 @@
                                SILLocation l) {
     assert(isa<EnumElementDecl>(c.getDecl()));
     auto &ci = SGF.getConstantInfo(c);
-    return Callee(Kind::EnumElement, SGF, None, c, ci.FormalPattern,
+    return Callee(Kind::EnumElement, SGF, c, ci.FormalPattern,
                   ci.FormalType, subs, l);
   }
-  static Callee forClassMethod(SILGenFunction &SGF, ArgumentSource &&selfValue,
+  static Callee forClassMethod(SILGenFunction &SGF,
                                SILDeclRef c, SubstitutionList subs,
                                SILLocation l) {
     auto base = SGF.SGM.Types.getOverriddenVTableEntry(c);
     auto &baseCI = SGF.getConstantInfo(base);
     auto &derivedCI = SGF.getConstantInfo(c);
-    return Callee(Kind::ClassMethod, SGF, std::move(selfValue), c,
+    return Callee(Kind::ClassMethod, SGF, c,
                   baseCI.FormalPattern, derivedCI.FormalType, subs, l);
   }
-  static Callee forSuperMethod(SILGenFunction &SGF, ArgumentSource &&selfValue,
+  static Callee forSuperMethod(SILGenFunction &SGF,
                                SILDeclRef c, SubstitutionList subs,
                                SILLocation l) {
     auto &ci = SGF.getConstantInfo(c);
-    return Callee(Kind::SuperMethod, SGF, std::move(selfValue), c,
+    return Callee(Kind::SuperMethod, SGF, c,
                   ci.FormalPattern, ci.FormalType, subs, l);
   }
   static Callee forWitnessMethod(SILGenFunction &SGF,
@@ -393,18 +342,16 @@
                                  SubstitutionList subs,
                                  SILLocation l) {
     auto &ci = SGF.getConstantInfo(c);
-    return Callee(Kind::WitnessMethod, SGF, None, c, ci.FormalPattern,
+    return Callee(Kind::WitnessMethod, SGF, c, ci.FormalPattern,
                   ci.FormalType, subs, l);
   }
-  static Callee forDynamic(SILGenFunction &SGF, ArgumentSource &&arg,
+  static Callee forDynamic(SILGenFunction &SGF,
                            SILDeclRef c, const SubstitutionList &constantSubs,
-                           CanAnyFunctionType partialSubstFormalType,
+                           CanAnyFunctionType substFormalType,
                            SubstitutionList subs, SILLocation l) {
     auto &ci = SGF.getConstantInfo(c);
     AbstractionPattern origFormalType = ci.FormalPattern;
 
-    auto selfType = getDynamicMethodSelfType(SGF, arg, c.getDecl());
-
     // Replace the original self type with the partially-applied subst type.
     auto origFormalFnType = cast<AnyFunctionType>(origFormalType.getType());
     if (auto genericFnType = dyn_cast<GenericFunctionType>(origFormalFnType)) {
@@ -418,17 +365,9 @@
         cast<FunctionType>(genericFnType->substGenericArgs(constantSubs)
                                         ->getCanonicalType());
     }
-    origFormalFnType = CanFunctionType::get(selfType,
-                                            origFormalFnType.getResult(),
-                                            origFormalFnType->getExtInfo());
     origFormalType.rewriteType(CanGenericSignature(), origFormalFnType);
 
-    // Add the self type clause to the partially-applied subst type.
-    auto substFormalType = CanFunctionType::get(selfType,
-                                                partialSubstFormalType,
-                                                origFormalFnType->getExtInfo());
-
-    return Callee(Kind::DynamicMethod, SGF, std::move(arg), c, origFormalType,
+    return Callee(Kind::DynamicMethod, SGF, c, origFormalType,
                   substFormalType, subs, l);
   }
 
@@ -457,10 +396,10 @@
     return SubstFormalInterfaceType;
   }
 
-  unsigned getNaturalUncurryLevel() const {
+  unsigned getParameterListCount() const {
     switch (kind) {
     case Kind::IndirectValue:
-      return 0;
+      return 1;
 
     case Kind::StandaloneFunction:
     case Kind::EnumElement:
@@ -468,7 +407,23 @@
     case Kind::SuperMethod:
     case Kind::WitnessMethod:
     case Kind::DynamicMethod:
-      return Constant.getUncurryLevel();
+      return Constant.getParameterListCount();
+    }
+
+    llvm_unreachable("Unhandled Kind in switch.");
+  }
+
+  bool requiresSelfValueForDispatch() const {
+    switch (kind) {
+    case Kind::IndirectValue:
+    case Kind::StandaloneFunction:
+    case Kind::EnumElement:
+    case Kind::WitnessMethod:
+      return false;
+    case Kind::ClassMethod:
+    case Kind::SuperMethod:
+    case Kind::DynamicMethod:
+      return true;
     }
 
     llvm_unreachable("Unhandled Kind in switch.");
@@ -498,21 +453,40 @@
     return result;
   }
 
-  ManagedValue getFnValueAtUncurryLevel(SILGenFunction &SGF,
-                                        unsigned level) const & {
+  SILDeclRef getCurriedConstant(bool isCurried) const {
+    if (isCurried) {
+      auto constant = Constant.asCurried();
+
+      // If we're currying a direct reference to a class-dispatched method,
+      // make sure we emit the right set of thunks.
+      if (kind == Kind::StandaloneFunction) {
+        if (auto func = Constant.getAbstractFunctionDecl()) {
+          if (getMethodDispatch(func) == MethodDispatch::Class) {
+            return constant.asDirectReference(true);
+          }
+        }
+      }
+
+      return constant;
+    }
+
+    return Constant;
+  }
+
+  ManagedValue getFnValue(SILGenFunction &SGF, bool isCurried,
+                          Optional<ManagedValue> borrowedSelf) const & {
     Optional<SILDeclRef> constant = None;
 
     if (!Constant) {
-      assert(level == 0 && "can't curry indirect function");
+      assert(!isCurried && "can't curry indirect function");
     } else {
-      unsigned uncurryLevel = Constant.getUncurryLevel();
-      assert(level <= uncurryLevel &&
-             "uncurrying past natural uncurry level of standalone function");
-      if (level < uncurryLevel) {
-        assert(level == 0);
-        constant = Constant.asCurried();
-      } else {
-        constant = Constant;
+      constant = getCurriedConstant(isCurried);
+
+      // If the call is curried, emit a direct call to the curry thunk.
+      if (constant->isCurried) {
+        auto constantInfo = SGF.getConstantInfo(*constant);
+        SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
+        return ManagedValue::forUnmanaged(ref);
       }
     }
 
@@ -522,51 +496,25 @@
       return IndirectValue;
 
     case Kind::StandaloneFunction: {
-      // If we're currying a direct reference to a class-dispatched method,
-      // make sure we emit the right set of thunks.
-      if (constant->isCurried && Constant.hasDecl())
-        if (auto func = Constant.getAbstractFunctionDecl())
-          if (getMethodDispatch(func) == MethodDispatch::Class)
-            constant = constant->asDirectReference(true);
-
       auto constantInfo = SGF.getConstantInfo(*constant);
       SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
       return ManagedValue::forUnmanaged(ref);
     }
-    case Kind::EnumElement: {
-      auto constantInfo = SGF.getConstantInfo(*constant);
-
-      // We should not end up here if the enum constructor call is fully
-      // applied.
-      assert(constant->isCurried);
-
-      SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
-      return ManagedValue::forUnmanaged(ref);
-    }
+    case Kind::EnumElement:
+      llvm_unreachable("Should have been curried");
     case Kind::ClassMethod: {
-      auto constantInfo = SGF.getConstantInfo(*constant);
-
-      // If the call is curried, emit a direct call to the curry thunk.
-      if (constant->isCurried) {
-        SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
-        return ManagedValue::forUnmanaged(ref);
-      }
-
       auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
 
       // Otherwise, do the dynamic dispatch inline.
       Scope S(SGF, Loc);
-      ManagedValue borrowedSelf =
-          SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
 
       SILValue methodVal;
       if (!constant->isForeign) {
-        methodVal = SGF.B.createClassMethod(
-            Loc, borrowedSelf.getValue(), *constant,
-            SILType::getPrimitiveObjectType(methodTy));
+        methodVal = SGF.emitClassMethodRef(
+            Loc, borrowedSelf->getValue(), *constant, methodTy);
       } else {
         methodVal = SGF.B.createObjCMethod(
-            Loc, borrowedSelf.getValue(), *constant,
+            Loc, borrowedSelf->getValue(), *constant,
             SILType::getPrimitiveObjectType(methodTy));
       }
       return ManagedValue::forUnmanaged(methodVal);
@@ -575,9 +523,8 @@
       assert(!constant->isCurried);
 
       Scope S(SGF, Loc);
-      ManagedValue self =
-          SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
-      ManagedValue castValue = borrowedCastToOriginalSelfType(SGF, Loc, self);
+      ManagedValue castValue = borrowedCastToOriginalSelfType(
+        SGF, Loc, *borrowedSelf);
 
       auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
       auto constantInfo =
@@ -594,15 +541,8 @@
     case Kind::WitnessMethod: {
       auto constantInfo = SGF.getConstantInfo(*constant);
 
-      // If the call is curried, emit a direct call to the curry thunk.
-      if (constant->isCurried) {
-        SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
-        return ManagedValue::forUnmanaged(ref);
-      }
-
-      auto proto = Constant.getDecl()
-                       ->getDeclContext()
-                       ->getAsProtocolOrProtocolExtensionContext();
+      auto proto = cast<ProtocolDecl>(
+        Constant.getDecl()->getDeclContext());
       auto lookupType = getSubstFormalType()
                             .getInput()
                             ->getRValueInstanceType()
@@ -612,52 +552,32 @@
           Loc, lookupType, ProtocolConformanceRef(proto), *constant,
           constantInfo.getSILType(), constant->isForeign);
       return ManagedValue::forUnmanaged(fn);
-      ;
     }
     case Kind::DynamicMethod: {
-      assert(!constant->isCurried);
-      assert(constant->isForeign);
-
-      // Lower the substituted type from the AST, which should have any generic
-      // parameters in the original signature erased to their upper bounds.
-      auto substFormalType = getSubstFormalType();
-      auto objcFormalType = substFormalType.withExtInfo(
-          substFormalType->getExtInfo().withSILRepresentation(
-              SILFunctionTypeRepresentation::ObjCMethod));
-      auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
-          *constant, objcFormalType);
-
-      auto closureType = replaceSelfTypeForDynamicLookup(
-          SGF.getASTContext(), fnType,
-          SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
-          Constant);
+      auto closureType = getDynamicMethodLoweredType(
+          SGF.SGM.M, *constant, getSubstFormalType());
 
       Scope S(SGF, Loc);
-      ManagedValue self =
-          SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
       SILValue fn = SGF.B.createObjCMethod(
-          Loc, self.getValue(), *constant,
-          SILType::getPrimitiveObjectType(closureType));
+          Loc, borrowedSelf->getValue(), *constant,
+          closureType);
       return ManagedValue::forUnmanaged(fn);
     }
     }
   }
 
-  CalleeTypeInfo getTypeInfoAtUncurryLevel(SILGenFunction &SGF,
-                                           unsigned level) const & {
+  CalleeTypeInfo getTypeInfo(SILGenFunction &SGF, bool isCurried) const & {
     Optional<SILDeclRef> constant = None;
 
     if (!Constant) {
-      assert(level == 0 && "can't curry indirect function");
+      assert(!isCurried && "can't curry indirect function");
     } else {
-      unsigned uncurryLevel = Constant.getUncurryLevel();
-      assert(level <= uncurryLevel &&
-             "uncurrying past natural uncurry level of standalone function");
-      if (level < uncurryLevel) {
-        assert(level == 0);
-        constant = Constant.asCurried();
-      } else {
-        constant = Constant;
+      constant = getCurriedConstant(isCurried);
+
+      // If the call is curried, emit a direct call to the curry thunk.
+      if (constant->isCurried) {
+        auto constantInfo = SGF.getConstantInfo(*constant);
+        return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
       }
     }
 
@@ -667,38 +587,16 @@
       return createCalleeTypeInfo(SGF, constant, IndirectValue.getType());
 
     case Kind::StandaloneFunction: {
-      // If we're currying a direct reference to a class-dispatched method,
-      // make sure we emit the right set of thunks.
-      if (constant->isCurried && Constant.hasDecl())
-        if (auto func = Constant.getAbstractFunctionDecl())
-          if (getMethodDispatch(func) == MethodDispatch::Class)
-            constant = constant->asDirectReference(true);
-
       auto constantInfo = SGF.getConstantInfo(*constant);
       return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
-      ;
     }
-    case Kind::EnumElement: {
-      auto constantInfo = SGF.getConstantInfo(*constant);
-
-      // We should not end up here if the enum constructor call is fully
-      // applied.
-      assert(constant->isCurried);
-      return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
-    }
+    case Kind::EnumElement:
+      llvm_unreachable("Should have been curried");
     case Kind::ClassMethod: {
-      // If the call is curried, emit a direct call to the curry thunk.
-      if (constant->isCurried) {
-        auto constantInfo = SGF.getConstantInfo(*constant);
-        return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
-      }
-
-      // Otherwise, grab the override info.
       auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant);
       return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
     }
     case Kind::SuperMethod: {
-      assert(!constant->isCurried);
       auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
       auto constantInfo =
           SGF.SGM.Types.getConstantOverrideInfo(*constant, base);
@@ -709,23 +607,8 @@
       return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
     }
     case Kind::DynamicMethod: {
-      assert(!constant->isCurried);
-
-      // Lower the substituted type from the AST, which should have any generic
-      // parameters in the original signature erased to their upper bounds.
-      auto substFormalType = getSubstFormalType();
-      auto objcFormalType = substFormalType.withExtInfo(
-          substFormalType->getExtInfo().withSILRepresentation(
-              SILFunctionTypeRepresentation::ObjCMethod));
-      auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
-          *constant, objcFormalType);
-
-      auto closureType = replaceSelfTypeForDynamicLookup(
-          SGF.getASTContext(), fnType,
-          SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
-          Constant);
-
-      SILType formalType = SILType::getPrimitiveObjectType(closureType);
+      auto formalType = getDynamicMethodLoweredType(
+          SGF.SGM.M, *constant, getSubstFormalType());
       return createCalleeTypeInfo(SGF, constant, formalType);
     }
     }
@@ -743,11 +626,7 @@
   /// lowering, such as a builtin, or return null if there is no specialized
   /// emitter.
   Optional<SpecializedEmitter>
-  getSpecializedEmitter(SILGenModule &SGM, unsigned uncurryLevel) const {
-    // Currently we have no curried known functions.
-    if (uncurryLevel != 0)
-      return None;
-
+  getSpecializedEmitter(SILGenModule &SGM) const {
     switch (kind) {
     case Kind::StandaloneFunction: {
       return SpecializedEmitter::forDecl(SGM, Constant);
@@ -805,17 +684,10 @@
 
   /// The lvalue or rvalue representing the argument source of self.
   ArgumentSource selfParam;
-  Expr *selfApplyExpr = nullptr;
   Type selfType;
   std::vector<ApplyExpr*> callSites;
   Expr *sideEffect = nullptr;
 
-  /// When visiting expressions, sometimes we need to emit self before we know
-  /// what the actual callee is. In such cases, we assume that we are passing
-  /// self at +0 and then after we know what the callee is, we check if the
-  /// self is passed at +1. If so, we add an extra retain.
-  bool assumedPlusZeroSelf = false;
-
   SILGenApply(SILGenFunction &SGF)
     : SGF(SGF)
   {}
@@ -833,17 +705,9 @@
   void setSelfParam(ArgumentSource &&theSelfParam, Expr *theSelfApplyExpr) {
     assert(!selfParam && "already set this!");
     selfParam = std::move(theSelfParam);
-    selfApplyExpr = theSelfApplyExpr;
     selfType = theSelfApplyExpr->getType();
   }
 
-  void setSelfParam(ArgumentSource &&theSelfParam, Type selfType) {
-    assert(!selfParam && "already set this!");
-    selfParam = std::move(theSelfParam);
-    selfApplyExpr = nullptr;
-    selfType = selfType;
-  }
-
   void decompose(Expr *e) {
     visit(e);
   }
@@ -918,8 +782,8 @@
                                        /*objc=*/true, {}, {});
   }
 
-  void processProtocolDecl(DeclRefExpr *e, AbstractFunctionDecl *afd,
-                           ProtocolDecl *proto) {
+  void processProtocolMethod(DeclRefExpr *e, AbstractFunctionDecl *afd,
+                             ProtocolDecl *proto) {
     assert(!callSites.empty());
     ApplyExpr *thisCallSite = callSites.back();
     callSites.pop_back();
@@ -952,139 +816,87 @@
     SILDeclRef constant(afd, kind);
     constant = constant.asForeign(afd->isObjC());
 
-    // Prepare the callee.  This can modify both selfValue and subs.
+    // Prepare the callee.
     Callee theCallee = Callee::forWitnessMethod(
         SGF, selfValue.getSubstRValueType(),
         constant, subs, e);
-    assumedPlusZeroSelf =
-        selfValue.isRValue() &&
-        selfValue.forceAndPeekRValue(SGF).peekIsPlusZeroRValueOrTrivial();
 
     setSelfParam(std::move(selfValue), thisCallSite);
     setCallee(std::move(theCallee));
   }
 
-  bool processAbstractFunctionDecl(DeclRefExpr *e, AbstractFunctionDecl *afd) {
-    // We have four cases to deal with here:
-    //
-    //  1) for a "static" / "type" method, the base is a metatype.
-    //  2) for a classbound protocol, the base is a class-bound protocol
-    //  rvalue,
-    //     which is loadable.
-    //  3) for a mutating method, the base has inout type.
-    //  4) for a nonmutating method, the base is a general archetype
-    //     rvalue, which is address-only.  The base is passed at +0, so it
-    //     isn't
-    //     consumed.
-    //
-    // In the last case, the AST has this call typed as being applied
-    // to an rvalue, but the witness is actually expecting a pointer
-    // to the +0 value in memory.  We just pass in the address since
-    // archetypes are address-only.
-
-    if (auto *proto = dyn_cast<ProtocolDecl>(afd->getDeclContext())) {
-      processProtocolDecl(e, afd, proto);
-      return true;
-    }
-
-    Optional<SILDeclRef::Kind> kind;
-    bool isDynamicallyDispatched;
-    bool requiresAllocRefDynamic = false;
-
-    // Determine whether the method is dynamically dispatched.
-    if (e->getAccessSemantics() != AccessSemantics::Ordinary) {
-      isDynamicallyDispatched = false;
-    } else {
-      switch (getMethodDispatch(afd)) {
-      case MethodDispatch::Class:
-        isDynamicallyDispatched = true;
-        break;
-      case MethodDispatch::Static:
-        isDynamicallyDispatched = false;
-        break;
-      }
-    }
-
-    if (isa<FuncDecl>(afd) && isDynamicallyDispatched) {
-      kind = SILDeclRef::Kind::Func;
-    } else if (auto ctor = dyn_cast<ConstructorDecl>(afd)) {
-      ApplyExpr *thisCallSite = callSites.back();
-      // Required constructors are dynamically dispatched when the 'self'
-      // value is not statically derived.
-      if (ctor->isRequired() &&
-          thisCallSite->getArg()->getType()->is<AnyMetatypeType>() &&
-          !thisCallSite->getArg()->isStaticallyDerivedMetatype()) {
-        if (requiresForeignEntryPoint(afd)) {
-          // When we're performing Objective-C dispatch, we don't have an
-          // allocating constructor to call. So, perform an alloc_ref_dynamic
-          // and pass that along to the initializer.
-          requiresAllocRefDynamic = true;
-          kind = SILDeclRef::Kind::Initializer;
-        } else {
-          kind = SILDeclRef::Kind::Allocator;
-        }
-      } else {
-        isDynamicallyDispatched = false;
-      }
-    }
-
-    if (!isDynamicallyDispatched)
+  bool isClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
+    if (e->getAccessSemantics() != AccessSemantics::Ordinary)
       return false;
 
-    // At this point, we know for sure that we are actually dynamically
-    // dispatched.
+    if (getMethodDispatch(afd) == MethodDispatch::Static)
+      return false;
+
+    if (auto ctor = dyn_cast<ConstructorDecl>(afd)) {
+      // Non-required initializers are statically dispatched.
+      if (!ctor->isRequired())
+        return false;
+
+      // Required constructors are statically dispatched when the 'self'
+      // value is statically derived.
+      ApplyExpr *thisCallSite = callSites.back();
+      assert(thisCallSite->getArg()->getType()->is<AnyMetatypeType>());
+      if (thisCallSite->getArg()->isStaticallyDerivedMetatype())
+        return false;
+    }
+
+    // Ok, we're dynamically dispatched.
+    return true;
+  }
+
+  void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
+    SILDeclRef::Kind kind;
+    bool requiresAllocRefDynamic = false;
+
+    if (isa<FuncDecl>(afd)) {
+      kind = SILDeclRef::Kind::Func;
+    } else {
+      if (requiresForeignEntryPoint(afd)) {
+        // When we're performing Objective-C dispatch, we don't have an
+        // allocating constructor to call. So, perform an alloc_ref_dynamic
+        // and pass that along to the initializer.
+        requiresAllocRefDynamic = true;
+        kind = SILDeclRef::Kind::Initializer;
+      } else {
+        kind = SILDeclRef::Kind::Allocator;
+      }
+    }
+
     ApplyExpr *thisCallSite = callSites.back();
     callSites.pop_back();
 
-    // Emit the rvalue for self, allowing for guaranteed plus zero if we
-    // have a func.
-    bool AllowPlusZero = kind && *kind == SILDeclRef::Kind::Func;
-    RValue self = SGF.emitRValue(
-        thisCallSite->getArg(),
-        AllowPlusZero ? SGFContext::AllowGuaranteedPlusZero : SGFContext());
-
-    // If we allowed for PlusZero and we *did* get the value back at +0,
-    // then we assumed that self could be passed at +0. We will check later
-    // if the actual callee passes self at +1 later when we know its actual
-    // type.
-    assumedPlusZeroSelf =
-        AllowPlusZero && self.peekIsPlusZeroRValueOrTrivial();
-
     // If we require a dynamic allocation of the object here, do so now.
     if (requiresAllocRefDynamic) {
       SILLocation loc = thisCallSite->getArg();
+      RValue selfMetatype = SGF.emitRValue(thisCallSite->getArg());
       auto selfValue =
-          allocateObjCObject(std::move(self).getAsSingleValue(SGF, loc), loc);
-      self = RValue(SGF, loc, selfValue.getType().getSwiftRValueType(),
-                    selfValue);
+          allocateObjCObject(std::move(selfMetatype).getAsSingleValue(SGF, loc), loc);
+      RValue self = RValue(SGF, loc, selfValue.getType().getSwiftRValueType(),
+                           selfValue);
+      ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
+      setSelfParam(std::move(selfArgSource), thisCallSite);
+    } else {
+      ArgumentSource selfArgSource(thisCallSite->getArg());
+      setSelfParam(std::move(selfArgSource), thisCallSite);
     }
 
-    auto constant = SILDeclRef(afd, kind.getValue())
+    auto constant = SILDeclRef(afd, kind)
                         .asForeign(requiresForeignEntryPoint(afd));
 
-    ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
     auto subs = e->getDeclRef().getSubstitutions();
-    SILLocation loc(thisCallSite->getArg());
-    setCallee(Callee::forClassMethod(SGF, selfArgSource.delayedBorrow(SGF),
-                                     constant, subs, e));
-
-    setSelfParam(std::move(selfArgSource), thisCallSite);
-    return true;
+    setCallee(Callee::forClassMethod(SGF, constant, subs, e));
   }
 
   //
   // Known callees.
   //
   void visitDeclRefExpr(DeclRefExpr *e) {
-    // If we need to perform dynamic dispatch for the given function,
-    // emit class_method to do so.
-    if (auto *afd = dyn_cast<AbstractFunctionDecl>(e->getDecl())) {
-      // If after processing the abstract function decl, we do not have any more
-      // work, just return.
-      if (processAbstractFunctionDecl(e, afd)) {
-        return;
-      }
-    }
+    SubstitutionList subs = e->getDeclRef().getSubstitutions();
 
     // If this is a direct reference to a vardecl, just emit its value directly.
     // Recursive references to callable declarations are allowed.
@@ -1093,38 +905,45 @@
       return;
     }
 
+    // Enum case constructor references are open-coded.
+    if (auto *eed = dyn_cast<EnumElementDecl>(e->getDecl())) {
+      setCallee(Callee::forEnumElement(SGF, SILDeclRef(e->getDecl()), subs, e));
+      return;
+    }
+
+    // Ok, we have a constructor or a function.
+    auto *afd = cast<AbstractFunctionDecl>(e->getDecl());
+
+    // Witness method or @objc protocol dispatch.
+    if (auto *proto = dyn_cast<ProtocolDecl>(afd->getDeclContext())) {
+      processProtocolMethod(e, afd, proto);
+      return;
+    }
+
+    // VTable class method or @objc class method dispatch.
+    if (isClassMethod(e, afd)) {
+      processClassMethod(e, afd);
+      return;
+    }
+
+    // Otherwise, we have a statically-dispatched call.
     auto constant = SILDeclRef(e->getDecl())
       .asForeign(!isConstructorWithGeneratedAllocatorThunk(e->getDecl())
                  && requiresForeignEntryPoint(e->getDecl()));
 
-    auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
+    auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(afd);
+    if (afd->getDeclContext()->isLocalContext() &&
+        !captureInfo.hasGenericParamCaptures())
+      subs = SubstitutionList();
 
-    CaptureInfo captureInfo;
-
-    // Otherwise, we have a statically-dispatched call.
-    SubstitutionList subs = e->getDeclRef().getSubstitutions();
-
-    if (afd) {
-      captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(afd);
-      if (afd->getDeclContext()->isLocalContext() &&
-          !captureInfo.hasGenericParamCaptures())
-        subs = SubstitutionList();
-    }
-
-    // Enum case constructor references are open-coded.
-    if (isa<EnumElementDecl>(e->getDecl()))
-      setCallee(Callee::forEnumElement(SGF, constant, subs, e));
-    else
-      setCallee(Callee::forDirect(SGF, constant, subs, e));
+    setCallee(Callee::forDirect(SGF, constant, subs, e));
     
     // If the decl ref requires captures, emit the capture params.
-    if (afd) {
-      if (!captureInfo.getCaptures().empty()) {
-        SmallVector<ManagedValue, 4> captures;
-        SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
-                         captures);
-        applyCallee->setCaptures(std::move(captures));
-      }
+    if (!captureInfo.getCaptures().empty()) {
+      SmallVector<ManagedValue, 4> captures;
+      SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
+                       captures);
+      applyCallee->setCaptures(std::move(captures));
     }
   }
   
@@ -1168,6 +987,7 @@
     setCallee(Callee::forDirect(SGF,
                 SILDeclRef(e->getDecl(), SILDeclRef::Kind::Initializer), subs, e));
   }
+
   void visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e) {
     setSideEffect(e->getLHS());
     visit(e->getRHS());
@@ -1249,8 +1069,7 @@
     ArgumentSource superArgSource(arg, std::move(super));
     if (!canUseStaticDispatch(SGF, constant)) {
       // ObjC super calls require dynamic dispatch.
-      setCallee(Callee::forSuperMethod(SGF, superArgSource.delayedBorrow(SGF),
-                                       constant, substitutions, fn));
+      setCallee(Callee::forSuperMethod(SGF, constant, substitutions, fn));
     } else {
       // Native Swift super calls to final methods are direct.
       setCallee(Callee::forDirect(SGF, constant, substitutions, fn));
@@ -1419,8 +1238,7 @@
       // Dynamic dispatch to the initializer.
       Scope S(SGF, expr);
       setCallee(Callee::forClassMethod(
-          SGF, selfArgSource.delayedBorrow(SGF),
-          constant, subs, fn));
+          SGF, constant, subs, fn));
     } else {
       // Directly call the peer constructor.
       setCallee(
@@ -1515,8 +1333,11 @@
       auto substFormalType =
         cast<FunctionType>(dynamicMemberRef->getType()->getCanonicalType()
                                             .getAnyOptionalObjectType());
-      setCallee(Callee::forDynamic(SGF, baseArgSource.delayedBorrow(SGF),
-                                   member, memberRef.getSubstitutions(),
+      substFormalType = CanFunctionType::get(
+        dynamicMemberRef->getBase()->getType()->getCanonicalType(),
+        substFormalType, AnyFunctionType::ExtInfo());
+
+      setCallee(Callee::forDynamic(SGF, member, memberRef.getSubstitutions(),
                                    substFormalType, {}, e));
       setSelfParam(std::move(baseArgSource), dynamicMemberRef);
     };
@@ -1846,6 +1667,7 @@
   }
 
   // Emit the raw application.
+  loc.decodeDebugLoc(SGM.M.getASTContext().SourceMgr);
   SILValue rawDirectResult = emitRawApply(*this, loc, fn, subs, args,
                                           substFnType, options,
                                           indirectResultAddrs);
@@ -3892,50 +3714,6 @@
     ArgumentSource &&forward() && {
       return std::move(ArgValue);
     }
-
-    /// Returns true if the argument of this value is a single valued RValue
-    /// that is passed either at plus zero or is trivial.
-    bool isArgPlusZeroOrTrivialRValue() {
-      if (!ArgValue.isRValue())
-        return false;
-      return ArgValue.peekRValue().peekIsPlusZeroRValueOrTrivial();
-    }
-
-    /// If callsite has an argument that is a plus zero or trivial rvalue, emit
-    /// a retain so that the argument is at PlusOne.
-    void convertToPlusOneFromPlusZero(SILGenFunction &SGF) {
-      assert(isArgPlusZeroOrTrivialRValue() && "Must have a plus zero or "
-             "trivial rvalue as an argument.");
-      SILValue ArgSILValue = ArgValue.peekRValue().peekScalarValue();
-      SILType ArgTy = ArgSILValue->getType();
-
-      // If we are trivial, there is no difference in between +1 and +0 since
-      // a trivial object is not reference counted.
-      if (ArgTy.isTrivial(SGF.SGM.M))
-        return;
-
-      // Grab the SILLocation and the new managed value.
-      SILLocation ArgLoc = ArgValue.getKnownRValueLocation();
-      ManagedValue ArgManagedValue;
-      if (ArgSILValue->getType().isAddress()) {
-        auto result = SGF.emitTemporaryAllocation(ArgLoc,
-                                                  ArgSILValue->getType());
-        SGF.B.createCopyAddr(ArgLoc, ArgSILValue, result,
-                             IsNotTake, IsInitialization);
-        ArgManagedValue = SGF.emitManagedBufferWithCleanup(result);
-      } else {
-        ArgManagedValue = SGF.emitManagedRetain(ArgLoc, ArgSILValue);
-      }
-
-      // Ok now we make our transformation. First set ArgValue to a used albeit
-      // invalid, empty ArgumentSource.
-      ArgValue = ArgumentSource();
-
-      // Reassign ArgValue.
-      RValue NewRValue = RValue(SGF, ArgLoc, ArgTy.getSwiftRValueType(),
-                                 ArgManagedValue);
-      ArgValue = ArgumentSource(ArgLoc, std::move(NewRValue));
-    }
   };
 
   /// Once the Callee and CallSites have been prepared by SILGenApply,
@@ -3957,28 +3735,21 @@
     std::vector<CallSite> extraSites;
     Callee callee;
     FormalEvaluationScope initialWritebackScope;
-    unsigned uncurries;
-    bool applied;
-    bool assumedPlusZeroSelf;
+    unsigned expectedSiteCount;
 
   public:
     /// Create an emission for a call of the given callee.
     CallEmission(SILGenFunction &SGF, Callee &&callee,
-                 FormalEvaluationScope &&writebackScope,
-                 bool assumedPlusZeroSelf = false)
+                 FormalEvaluationScope &&writebackScope)
         : SGF(SGF), callee(std::move(callee)),
           initialWritebackScope(std::move(writebackScope)),
-          uncurries(callee.getNaturalUncurryLevel() + 1), applied(false),
-          assumedPlusZeroSelf(assumedPlusZeroSelf) {}
+          expectedSiteCount(callee.getParameterListCount()) {}
 
     /// Add a level of function application by passing in its possibly
     /// unevaluated arguments and their formal type.
     void addCallSite(CallSite &&site) {
-      assert(!applied && "already applied!");
-
       // Append to the main argument list if we have uncurry levels remaining.
-      if (uncurries > 0) {
-        --uncurries;
+      if (uncurriedSites.size() < expectedSiteCount) {
         uncurriedSites.push_back(std::move(site));
         return;
       }
@@ -3994,45 +3765,23 @@
       addCallSite(CallSite{std::forward<T>(args)...});
     }
 
-    /// If we assumed that self was being passed at +0 before we knew what the
-    /// final uncurried level of the callee was, but given the final uncurried
-    /// level of the callee, we are actually passing self at +1, add in a retain
-    /// of self.
-    void convertSelfToPlusOneFromPlusZero() {
-      // Self is always the first callsite.
-      if (!uncurriedSites[0].isArgPlusZeroOrTrivialRValue())
-        return;
-
-      // Insert an invalid ArgumentSource into uncurriedSites[0] so it is.
-      uncurriedSites[0].convertToPlusOneFromPlusZero(SGF);
-    }
-
     /// Is this a fully-applied enum element constructor call?
     bool isEnumElementConstructor() {
-      return (callee.kind == Callee::Kind::EnumElement && uncurries == 0);
+      return (callee.kind == Callee::Kind::EnumElement &&
+              uncurriedSites.size() == expectedSiteCount);
     }
 
     /// True if this is a completely unapplied super method call
-    bool isPartiallyAppliedSuperMethod(unsigned uncurryLevel) {
+    bool isPartiallyAppliedSuperMethod() {
       return (callee.kind == Callee::Kind::SuperMethod &&
-              uncurryLevel == 0);
+              uncurriedSites.size() == 1);
     }
 
     RValue apply(SGFContext C = SGFContext()) {
       initialWritebackScope.verify();
 
-      assert(!applied && "already applied!");
-
-      applied = true;
-
-      // Get the callee value at the needed uncurry level, uncurrying as
-      // much as possible. If the number of calls is less than the natural
-      // uncurry level, the callee emission might create a curry thunk.
-      unsigned uncurryLevel = callee.getNaturalUncurryLevel() - uncurries;
-
       // Emit the first level of call.
-      FirstLevelApplicationResult firstLevelResult =
-          applyFirstLevelCallee(uncurryLevel, C);
+      auto firstLevelResult = applyFirstLevelCallee(C);
 
       // End of the initial writeback scope.
       initialWritebackScope.verify();
@@ -4061,17 +3810,8 @@
           firstLevelResult.foreignSelf, C, formalTypeThrows);
     }
 
-    ~CallEmission() { assert(applied && "never applied!"); }
-
     // Movable, but not copyable.
-    CallEmission(CallEmission &&e)
-        : SGF(e.SGF), uncurriedSites(std::move(e.uncurriedSites)),
-          extraSites(std::move(e.extraSites)), callee(std::move(e.callee)),
-          initialWritebackScope(std::move(e.initialWritebackScope)),
-          uncurries(e.uncurries), applied(e.applied),
-          assumedPlusZeroSelf(e.assumedPlusZeroSelf) {
-      e.applied = true;
-    }
+    CallEmission(CallEmission &&e) = default;
 
   private:
     CallEmission(const CallEmission &) = delete;
@@ -4130,19 +3870,17 @@
 
     FirstLevelApplicationResult
     applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
-                            unsigned uncurryLevel, SGFContext C);
+                            SGFContext C);
 
     FirstLevelApplicationResult
-    applyPartiallyAppliedSuperMethod(unsigned uncurryLevel, SGFContext C);
+    applyPartiallyAppliedSuperMethod(SGFContext C);
 
     FirstLevelApplicationResult
-    applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C);
+    applyEnumElementConstructor(SGFContext C);
 
-    FirstLevelApplicationResult applyNormalCall(unsigned uncurryLevel,
-                                                SGFContext C);
+    FirstLevelApplicationResult applyNormalCall(SGFContext C);
 
-    FirstLevelApplicationResult applyFirstLevelCallee(unsigned uncurryLevel,
-                                                      SGFContext C);
+    FirstLevelApplicationResult applyFirstLevelCallee(SGFContext C);
 
     RValue applyRemainingCallSites(RValue &&result,
                                    AbstractionPattern origFormalType,
@@ -4165,25 +3903,27 @@
 }
 
 CallEmission::FirstLevelApplicationResult
-CallEmission::applyFirstLevelCallee(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyFirstLevelCallee(SGFContext C) {
   // Check for a specialized emitter.
-  if (auto emitter = callee.getSpecializedEmitter(SGF.SGM, uncurryLevel)) {
-    return applySpecializedEmitter(emitter.getValue(), uncurryLevel, C);
+  if (uncurriedSites.size() == expectedSiteCount) {
+    if (auto emitter = callee.getSpecializedEmitter(SGF.SGM)) {
+      return applySpecializedEmitter(emitter.getValue(), C);
+    }
   }
 
-  if (isPartiallyAppliedSuperMethod(uncurryLevel)) {
-    return applyPartiallyAppliedSuperMethod(uncurryLevel, C);
+  if (isPartiallyAppliedSuperMethod()) {
+    return applyPartiallyAppliedSuperMethod(C);
   }
 
   if (isEnumElementConstructor()) {
-    return applyEnumElementConstructor(uncurryLevel, C);
+    return applyEnumElementConstructor(C);
   }
 
-  return applyNormalCall(uncurryLevel, C);
+  return applyNormalCall(C);
 }
 
 CallEmission::FirstLevelApplicationResult
-CallEmission::applyNormalCall(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyNormalCall(SGFContext C) {
   FirstLevelApplicationResult firstLevelResult;
 
   // We use the context emit-into initialization only for the
@@ -4193,16 +3933,15 @@
   firstLevelResult.formalType = callee.getSubstFormalType();
   auto origFormalType = callee.getOrigFormalType();
 
+  bool isCurried = (uncurriedSites.size() < callee.getParameterListCount());
+
   // Get the callee type information.
-  CalleeTypeInfo calleeTypeInfo =
-      callee.getTypeInfoAtUncurryLevel(SGF, uncurryLevel);
-  ManagedValue mv = callee.getFnValueAtUncurryLevel(SGF, uncurryLevel);
+  auto calleeTypeInfo = callee.getTypeInfo(SGF, isCurried);
 
   // In C language modes, substitute the type of the AbstractionPattern
   // so that we won't see type parameters down when we try to form bridging
   // conversions.
-  CanSILFunctionType calleeFnTy = mv.getType().castTo<SILFunctionType>();
-  if (calleeFnTy->getLanguage() == SILFunctionLanguage::C) {
+  if (calleeTypeInfo.substFnType->getLanguage() == SILFunctionLanguage::C) {
     if (auto genericFnType =
           dyn_cast<GenericFunctionType>(origFormalType.getType())) {
       auto fnType = genericFnType->substGenericArgs(callee.getSubstitutions());
@@ -4220,20 +3959,6 @@
       SGF, calleeTypeInfo, uncurriedSites.back().Loc, uncurriedContext);
   ArgumentScope argScope(SGF, uncurriedSites.back().Loc);
 
-  // Now that we know the substFnType, check if we assumed that we were
-  // passing self at +0. If we did and self is not actually passed at +0,
-  // retain Self.
-  if (assumedPlusZeroSelf) {
-    // If the final emitted function does not have a self param or it does
-    // have a self param that is consumed, convert what we think is self
-    // to
-    // be plus zero.
-    if (!calleeTypeInfo.substFnType->hasSelfParam() ||
-        calleeTypeInfo.substFnType->getSelfParameter().isConsumed()) {
-      convertSelfToPlusOneFromPlusZero();
-    }
-  }
-
   // Emit the arguments.
   SmallVector<ManagedValue, 4> uncurriedArgs;
   Optional<SILLocation> uncurriedLoc;
@@ -4245,6 +3970,15 @@
       firstLevelResult.formalType, origFormalType, calleeTypeInfo.substFnType,
       calleeTypeInfo.foreignError, calleeTypeInfo.foreignSelf, uncurriedArgs,
       uncurriedLoc, formalApplyType);
+
+  // Now evaluate the callee.
+  Optional<ManagedValue> borrowedSelf;
+  if (callee.requiresSelfValueForDispatch()) {
+    borrowedSelf = uncurriedArgs.back();
+  }
+
+  auto mv = callee.getFnValue(SGF, isCurried, borrowedSelf);
+
   // Emit the uncurried call.
   firstLevelResult.value =
       SGF.emitApply(std::move(resultPlan), std::move(argScope),
@@ -4255,14 +3989,10 @@
 }
 
 CallEmission::FirstLevelApplicationResult
-CallEmission::applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyEnumElementConstructor(SGFContext C) {
   FirstLevelApplicationResult firstLevelResult;
-  assert(!assumedPlusZeroSelf);
   SGFContext uncurriedContext = (extraSites.empty() ? C : SGFContext());
 
-  // The uncurry level in an enum element constructor is weird, so
-  // it's quite fortunate that we can completely ignore it.
-
   // Get the callee type information.
   //
   // Enum payloads are always stored at the abstraction level of the
@@ -4310,10 +4040,8 @@
 }
 
 CallEmission::FirstLevelApplicationResult
-CallEmission::applyPartiallyAppliedSuperMethod(unsigned uncurryLevel,
-                                               SGFContext C) {
+CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) {
   FirstLevelApplicationResult firstLevelResult;
-  assert(uncurryLevel == 0);
 
   // We want to emit the arguments as fully-substituted values
   // because that's what the partially applied super method expects;
@@ -4322,20 +4050,6 @@
   auto substFnType =
       SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType);
 
-  // Now that we know the substFnType, check if we assumed that we were
-  // passing self at +0. If we did and self is not actually passed at +0,
-  // retain Self.
-  if (assumedPlusZeroSelf) {
-    // If the final emitted function does not have a self param or it does
-    // have a self param that is consumed, convert what we think is self
-    // to
-    // be plus zero.
-    if (!substFnType->hasSelfParam() ||
-        substFnType->getSelfParameter().isConsumed()) {
-      convertSelfToPlusOneFromPlusZero();
-    }
-  }
-
   // Emit the arguments.
   SmallVector<ManagedValue, 4> uncurriedArgs;
   Optional<SILLocation> uncurriedLoc;
@@ -4393,7 +4107,7 @@
 
 CallEmission::FirstLevelApplicationResult
 CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
-                                      unsigned uncurryLevel, SGFContext C) {
+                                      SGFContext C) {
   FirstLevelApplicationResult firstLevelResult;
 
   // We use the context emit-into initialization only for the
@@ -4402,8 +4116,6 @@
 
   ManagedValue mv;
 
-  assert(uncurryLevel == 0);
-
   // Get the callee type information. We want to emit the arguments as
   // fully-substituted values because that's what the specialized emitters
   // expect.
@@ -4412,19 +4124,6 @@
   auto substFnType =
       SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType);
 
-  // Now that we know the substFnType, check if we assumed that we were
-  // passing self at +0. If we did and self is not actually passed at +0,
-  // retain Self.
-  if (assumedPlusZeroSelf) {
-    // If the final emitted function does not have a self param or it does
-    // have a self param that is consumed, convert what we think is self to
-    // be plus zero.
-    if (!substFnType->hasSelfParam() ||
-        substFnType->getSelfParameter().isConsumed()) {
-      convertSelfToPlusOneFromPlusZero();
-    }
-  }
-
   // If we have an early emitter, just let it take over for the
   // uncurried call site.
   if (specializedEmitter.isEarlyEmitter()) {
@@ -4638,8 +4337,7 @@
   // Build the call.
   // Pass the writeback scope on to CallEmission so it can thread scopes through
   // nested calls.
-  CallEmission emission(SGF, apply.getCallee(), std::move(writebacks),
-                        apply.assumedPlusZeroSelf);
+  CallEmission emission(SGF, apply.getCallee(), std::move(writebacks));
 
   // Apply 'self' if provided.
   if (apply.selfParam) {
@@ -4686,8 +4384,13 @@
   auto origFormalType = callee.getOrigFormalType();
   auto substFormalType = callee.getSubstFormalType();
 
-  CalleeTypeInfo calleeTypeInfo = callee.getTypeInfoAtUncurryLevel(*this, 0);
-  ManagedValue mv = callee.getFnValueAtUncurryLevel(*this, 0);
+  auto calleeTypeInfo = callee.getTypeInfo(*this, /*isCurried=*/false);
+
+  Optional<ManagedValue> borrowedSelf;
+  if (callee.requiresSelfValueForDispatch())
+    borrowedSelf = args.back();
+  auto mv = callee.getFnValue(*this, /*isCurried=*/false,
+                              borrowedSelf);
 
   assert(!calleeTypeInfo.foreignError);
   assert(!calleeTypeInfo.foreignSelf.isImportAsMember());
@@ -5016,14 +4719,12 @@
   // Otherwise, if we have a non-final class dispatch to a normal method,
   // perform a dynamic dispatch.
   if (!isSuper)
-    return Callee::forClassMethod(SGF, selfValue.delayedBorrow(SGF), constant,
-                                  subs, loc);
+    return Callee::forClassMethod(SGF, constant, subs, loc);
 
   // If this is a "super." dispatch, we do a dynamic dispatch for objc methods
   // or non-final native Swift methods.
   if (!canUseStaticDispatch(SGF, constant))
-    return Callee::forSuperMethod(SGF, selfValue.delayedBorrow(SGF), constant,
-                                  subs, loc);
+    return Callee::forSuperMethod(SGF, constant, subs, loc);
 
   return Callee::forDirect(SGF, constant, subs, loc);
 }
@@ -5676,17 +5377,17 @@
                                        operand->getType().getSwiftRValueType(),
                                        memberMethodTy->getCanonicalType());
 
-    auto dynamicMethodTy = getDynamicMethodLoweredType(*this, operand, member,
+    auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member,
                                                        memberFnTy);
-    auto loweredMethodTy = SILType::getPrimitiveObjectType(dynamicMethodTy);
     SILValue memberArg = hasMemberBB->createPHIArgument(
         loweredMethodTy, ValueOwnershipKind::Owned);
 
     // Create the result value.
+    Scope applyScope(Cleanups, CleanupLocation(e));
     ManagedValue result =
       emitDynamicPartialApply(*this, e, memberArg, operand,
                               foreignMethodTy, methodTy);
-    Scope applyScope(Cleanups, CleanupLocation(e));
+
     RValue resultRV;
     if (isa<VarDecl>(e->getMember().getDecl())) {
       resultRV = emitMonomorphicApply(e, result, {},
@@ -5772,19 +5473,18 @@
     
     auto functionTy = CanFunctionType::get(base->getType().getSwiftRValueType(),
                                            methodTy);
-    auto dynamicMethodTy = getDynamicMethodLoweredType(*this, base, member,
+    auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member,
                                                        functionTy);
-    auto loweredMethodTy = SILType::getPrimitiveObjectType(dynamicMethodTy);
     SILValue memberArg = hasMemberBB->createPHIArgument(
         loweredMethodTy, ValueOwnershipKind::Owned);
     // Emit the application of 'self'.
+    Scope applyScope(Cleanups, CleanupLocation(e));
     ManagedValue result = emitDynamicPartialApply(*this, e, memberArg, base,
                                                   foreignMethodTy, methodTy);
     // Emit the index.
     llvm::SmallVector<ManagedValue, 2> indexArgs;
     std::move(index).getAll(indexArgs);
     
-    Scope applyScope(Cleanups, CleanupLocation(e));
     auto resultRV = emitMonomorphicApply(e, result, indexArgs,
                                          foreignMethodTy.getResult(), valueTy,
                                          ApplyOptions::DoesNotThrow,
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index f3a4cc2..ae0d272 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -127,6 +127,16 @@
   // Substitute into the witness function type.
   witnessFnTy = witnessFnTy.substGenericArgs(SGF.SGM.M, typeSubMap);
 
+  // We might have to re-abstract the 'self' value if it is an
+  // Optional.
+  AbstractionPattern origSelfType(witness->getInterfaceType());
+  origSelfType = origSelfType.getFunctionInputType();
+
+  swiftValue = SGF.emitSubstToOrigValue(loc, swiftValue,
+                                        origSelfType,
+                                        swiftValueType,
+                                        SGFContext());
+
   // The witness may be more abstract than the concrete value we're bridging,
   // for instance, if the value is a concrete instantiation of a generic type.
   //
@@ -345,6 +355,12 @@
   return results;
 }
 
+static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM,
+                                              CanAnyFunctionType blockType) {
+  return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType),
+                                         blockType, blockType->getExtInfo());
+}
+
 static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
                                        SILLocation loc,
                                        CanAnyFunctionType formalFuncType,
@@ -358,10 +374,7 @@
   SILFunctionConventions funcConv(funcTy, SGF.SGM.M);
 
   // Make sure we lower the component types of the formal block type.
-  formalBlockType =
-    SGF.SGM.Types.getBridgedFunctionType(AbstractionPattern(formalBlockType),
-                                         formalBlockType,
-                                         formalBlockType->getExtInfo());
+  formalBlockType = getBridgedBlockType(SGF.SGM, formalBlockType);
 
   // Set up the indirect result.
   SILType blockResultTy = blockTy->getAllResultsType();
@@ -498,6 +511,8 @@
   auto blockInterfaceTy = cast<SILFunctionType>(
     F.mapTypeOutOfContext(loweredBlockTy)->getCanonicalType());
 
+  assert(!blockInterfaceTy->isCoroutine());
+
   auto storageTy = SILBlockStorageType::get(loweredFuncTy);
   auto storageInterfaceTy = SILBlockStorageType::get(fnInterfaceTy);
 
@@ -535,8 +550,9 @@
   }
 
   auto invokeTy = SILFunctionType::get(
-      genericSig, extInfo, ParameterConvention::Direct_Unowned, params,
-      blockInterfaceTy->getResults(),
+      genericSig, extInfo, SILCoroutineKind::None,
+      ParameterConvention::Direct_Unowned, params, 
+      /*yields*/ {}, blockInterfaceTy->getResults(),
       blockInterfaceTy->getOptionalErrorResult(), getASTContext());
 
   // Create the invoke function. Borrow the mangling scheme from reabstraction
@@ -751,6 +767,9 @@
   // Collect the native arguments, which should all be +1.
   Scope scope(SGF.Cleanups, CleanupLocation::get(loc));
 
+  // Make sure we lower the component types of the formal block type.
+  formalBlockTy = getBridgedBlockType(SGF.SGM, formalBlockTy);
+
   assert(blockTy->getNumParameters() == funcTy->getNumParameters()
          && "block and function types don't match");
 
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index f782af6..c6f9aa8 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -229,7 +229,8 @@
 
     // On failure, we'll clean up everything (except self, which should have
     // been cleaned up before jumping here) and return nil instead.
-    SavedInsertionPoint savedIP(*this, failureBB, FunctionSection::Postmatter);
+    SILGenSavedInsertionPoint savedIP(*this, failureBB,
+                                      FunctionSection::Postmatter);
     failureExitBB = createBasicBlock();
     Cleanups.emitCleanupsForReturn(ctor);
     // Return nil.
@@ -275,7 +276,7 @@
   // SIL representation.
   SILValue selfValue;
   {
-    SavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
+    SILGenSavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
     assert(B.getInsertionBB()->empty() && "Epilog already set up?");
     
     auto cleanupLoc = CleanupLocation::get(ctor);
@@ -621,7 +622,8 @@
     loc.markAutoGenerated();
 
     // On failure, we'll clean up everything and return nil instead.
-    SavedInsertionPoint savedIP(*this, failureBB, FunctionSection::Postmatter);
+    SILGenSavedInsertionPoint savedIP(*this, failureBB,
+                                      FunctionSection::Postmatter);
 
     failureExitBB = createBasicBlock();
     failureExitArg = failureExitBB->createPHIArgument(
@@ -674,7 +676,7 @@
                                           ReturnDest.getDepth()) &&
            "emitting epilog in wrong scope");
 
-    SavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
+    SILGenSavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
     assert(B.getInsertionBB()->empty() && "Epilog already set up?");
     auto cleanupLoc = CleanupLocation(ctor);
 
@@ -857,8 +859,10 @@
     
     initConstantTy = SILFunctionType::get(initConstantTy->getGenericSignature(),
                                           initConstantTy->getExtInfo(),
+                                          SILCoroutineKind::None,
                                           ParameterConvention::Direct_Unowned,
                                           param,
+                                          /*yields*/ {},
                                           result,
                                           // TODO: throwing initializer?
                                           None,
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 4009cc0..11b1f41 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -396,7 +396,7 @@
     finalResult = emitManagedBufferWithCleanup(
         emitTemporaryAllocation(loc, resultTy), resultTL);
   } else {
-    SavedInsertionPoint IP(*this, contBB);
+    SILGenSavedInsertionPoint IP(*this, contBB);
     finalResult = B.createOwnedPHIArgument(resultTL.getLoweredType());
   }
 
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index ffe41f8..b969f52 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1125,7 +1125,7 @@
   // the initialization. Otherwise, mark it uninitialized for DI to resolve.
   if (auto *Init = entry.getInit()) {
     FullExpr Scope(Cleanups, CleanupLocation(Init));
-    emitExprInto(Init, initialization.get());
+    emitExprInto(Init, initialization.get(), SILLocation(PBD));
   } else {
     initialization->finishUninitialized(*this);
   }
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 0528044..2252d6c 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -361,7 +361,8 @@
   return ManagedValue(v, enterDestroyCleanup(v));
 }
 
-void SILGenFunction::emitExprInto(Expr *E, Initialization *I) {
+void SILGenFunction::emitExprInto(Expr *E, Initialization *I,
+                                  Optional<SILLocation> L) {
   // Handle the special case of copying an lvalue.
   if (auto load = dyn_cast<LoadExpr>(E)) {
     FormalEvaluationScope writeback(*this);
@@ -372,7 +373,7 @@
 
   RValue result = emitRValue(E, SGFContext(I));
   if (!result.isInContext())
-    std::move(result).forwardInto(*this, E, I);
+    std::move(result).forwardInto(*this, L ? *L : E, I);
 }
 
 namespace {
@@ -1042,8 +1043,11 @@
   // If the referenced decl isn't a VarDecl, it should be a constant of some
   // sort.
   SILDeclRef silDeclRef(decl);
-  if (silDeclRef.getUncurryLevel() > 0)
+  if (silDeclRef.getParameterListCount() == 2) {
+    // Unqualified reference to an instance method from a static context,
+    // without applying 'self'.
     silDeclRef = silDeclRef.asCurried();
+  }
 
   ManagedValue result = emitClosureValue(loc, silDeclRef, refType,
                                          declRef.getSubstitutions());
@@ -1414,7 +1418,7 @@
     SGF.eraseBasicBlock(catchBB);
   } else {
     // Otherwise, we need to emit it.
-    SavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter);
+    SILGenSavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter);
 
     ASTContext &ctx = SGF.getASTContext();
     auto error = catchBB->createPHIArgument(SILType::getExceptionType(ctx),
@@ -1887,9 +1891,11 @@
   case AnyFunctionType::Representation::Swift: {
     switch (sourceTy->getRepresentation()) {
     case SILFunctionType::Representation::Thin: {
-      auto v = SGF.B.createThinToThickFunction(loc, source.getValue(),
-        SILType::getPrimitiveObjectType(
-         adjustFunctionType(sourceTy, SILFunctionType::Representation::Thick)));
+      auto v = SGF.B.createThinToThickFunction(
+          loc, source.getValue(),
+          SILType::getPrimitiveObjectType(adjustFunctionType(
+              sourceTy, SILFunctionType::Representation::Thick,
+              SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
       // FIXME: what if other reabstraction is required?
       return ManagedValue(v, source.getCleanup());
     }
@@ -1913,9 +1919,11 @@
     switch (sourceTy->getRepresentation()) {
     case SILFunctionType::Representation::Thin: {
       // Make thick first.
-      auto v = SGF.B.createThinToThickFunction(loc, source.getValue(),
-        SILType::getPrimitiveObjectType(
-         adjustFunctionType(sourceTy, SILFunctionType::Representation::Thick)));
+      auto v = SGF.B.createThinToThickFunction(
+          loc, source.getValue(),
+          SILType::getPrimitiveObjectType(adjustFunctionType(
+              sourceTy, SILFunctionType::Representation::Thick,
+              SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
       source = ManagedValue(v, source.getCleanup());
       LLVM_FALLTHROUGH;
     }
@@ -2845,7 +2853,9 @@
   // Generate the closure value (if any) for the closure expr's function
   // reference.
   auto refType = e->getType()->getCanonicalType();
-  ManagedValue result = SGF.emitClosureValue(e, SILDeclRef(e),
+  SILLocation L = e;
+  L.markAutoGenerated();
+  ManagedValue result = SGF.emitClosureValue(L, SILDeclRef(e),
                                              refType, subs);
   return RValue(SGF, e, refType, result);
 }
@@ -3029,8 +3039,9 @@
     SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                              /*pseudogeneric*/ false,
                              /*noescape*/ false),
+    SILCoroutineKind::None,
     ParameterConvention::Direct_Unowned,
-    params, result, None, SGF.getASTContext());
+    params, {}, result, None, SGF.getASTContext());
   
   // Find the function and see if we already created it.
   SmallVector<CanType, 2> interfaceSubs;
@@ -3149,8 +3160,9 @@
     SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                              /*pseudogeneric*/ false,
                              /*noescape*/ false),
+    SILCoroutineKind::None,
     ParameterConvention::Direct_Unowned,
-    params, {}, None, SGF.getASTContext());
+    params, {}, {}, None, SGF.getASTContext());
   
   // Mangle the name of the thunk to see if we already created it.
   SmallString<64> nameBuf;
@@ -3317,8 +3329,9 @@
       SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                /*pseudogeneric*/ false,
                                /*noescape*/ false),
+    SILCoroutineKind::None,
       ParameterConvention::Direct_Unowned,
-      params, results, None, C);
+      params, /*yields*/ {}, results, None, C);
     
     // Mangle the name of the thunk to see if we already created it.
     SmallString<64> nameBuf;
@@ -3483,8 +3496,9 @@
       SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                /*pseudogeneric*/ false,
                                /*noescape*/ false),
+      SILCoroutineKind::None,
       ParameterConvention::Direct_Unowned,
-      params, results, None, C);
+      params, /*yields*/ {}, results, None, C);
     
     // Mangle the name of the thunk to see if we already created it.
     SmallString<64> nameBuf;
@@ -5066,37 +5080,25 @@
        llvm::function_ref<void(Expr *)> emitSubExpr) {
   Optional<FormalEvaluationScope> writebackScope;
 
-  Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
-
   // Emit the existential value.
-  SILGenFunction::OpaqueValueState state;
-
-  AccessKind accessKind;
   if (E->getExistentialValue()->getType()->is<LValueType>()) {
-    // Create a writeback scope for the access to the existential lvalue.
-    writebackScope.emplace(*this);
+    bool inserted = OpaqueValueExprs.insert({E->getOpaqueValue(), E}).second;
+    (void)inserted;
+    assert(inserted && "already have this opened existential?");
 
-    Type formalRValueType =
-      E->getOpaqueValue()->getType()->getWithoutSpecifierType();
+    emitSubExpr(E->getSubExpr());
+    return;
+  }
 
-    accessKind = E->getExistentialValue()->getLValueAccessKind();
-    auto lv = emitLValue(E->getExistentialValue(), accessKind);
-    lv = emitOpenExistentialLValue(E, std::move(lv),
-                                   CanArchetypeType(E->getOpenedArchetype()),
-                                   formalRValueType->getCanonicalType(),
-                                   accessKind);
-    auto addr = emitAddressOfLValue(E, std::move(lv), accessKind);
-    state = {addr, false, false};
-  } else {
-    accessKind = AccessKind::Read;
-    auto existentialValue = emitRValueAsSingleValue(
+  auto existentialValue = emitRValueAsSingleValue(
       E->getExistentialValue(),
       SGFContext::AllowGuaranteedPlusZero);
-  
-    state = emitOpenExistential(
+
+  Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
+  auto state = emitOpenExistential(
       E, existentialValue, E->getOpenedArchetype(),
-      getLoweredType(opaqueValueType), accessKind);
-  }
+      getLoweredType(opaqueValueType),
+      AccessKind::Read);
 
   // Register the opaque value for the projected existential.
   SILGenFunction::OpaqueValueRAII opaqueValueRAII(
diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp
index 7f39f0a..63dcf62 100644
--- a/lib/SILGen/SILGenForeignError.cpp
+++ b/lib/SILGen/SILGenForeignError.cpp
@@ -253,7 +253,8 @@
 void SILGenFunction::emitForeignErrorBlock(SILLocation loc,
                                            SILBasicBlock *errorBB,
                                            Optional<ManagedValue> errorSlot) {
-  SavedInsertionPoint savedIP(*this, errorBB, FunctionSection::Postmatter);
+  SILGenSavedInsertionPoint savedIP(*this, errorBB,
+                                    FunctionSection::Postmatter);
 
   // Load the error (taking responsibility for it).  In theory, this
   // is happening within conditional code, so we need to be only
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 8844bc6..f579dcc 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -475,9 +475,11 @@
                   SILFunctionType::ExtInfo()
                     .withRepresentation(SILFunctionType::Representation::
                                         CFunctionPointer),
+                  SILCoroutineKind::None,
                   ParameterConvention::Direct_Unowned,
                   SILParameterInfo(anyObjectMetaTy,
                                    ParameterConvention::Direct_Unowned),
+                  /*yields*/ {},
                   SILResultInfo(OptNSStringTy,
                                 ResultConvention::Autoreleased),
                   /*error result*/ None,
@@ -577,8 +579,10 @@
                     // Should be C calling convention, but NSApplicationMain
                     // has an overlay to fix the type of argv.
                     .withRepresentation(SILFunctionType::Representation::Thin),
+                  SILCoroutineKind::None,
                   ParameterConvention::Direct_Unowned,
                   argTypes,
+                  /*yields*/ {},
                   SILResultInfo(argc->getType().getSwiftRValueType(),
                                 ResultConvention::Unowned),
                   /*error result*/ None,
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 85603c9..978debb 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -518,6 +518,8 @@
   void emitForeignToNativeThunk(SILDeclRef thunk);
   /// Generates a thunk from a native function to the conventions.
   void emitNativeToForeignThunk(SILDeclRef thunk);
+  /// Generates a resilient method dispatch thunk.
+  void emitDispatchThunk(SILDeclRef constant);
   
   /// Generate a nullary function that returns the given value.
   void emitGeneratorFunction(SILDeclRef function, Expr *value);
@@ -952,7 +954,8 @@
   /// Generate SIL for the given expression, storing the final result into the
   /// specified Initialization buffer(s). This avoids an allocation and copy if
   /// the result would be allocated into temporary memory normally.
-  void emitExprInto(Expr *E, Initialization *I);
+  /// The location defaults to \c E.
+  void emitExprInto(Expr *E, Initialization *I, Optional<SILLocation> L = None);
 
   /// Emit the given expression as an r-value.
   RValue emitRValue(Expr *E, SGFContext C = SGFContext());
@@ -1044,6 +1047,11 @@
   SILValue emitDynamicMethodRef(SILLocation loc, SILDeclRef constant,
                                 CanSILFunctionType constantTy);
 
+  /// Returns a reference to a vtable-dispatched method.
+  SILValue emitClassMethodRef(SILLocation loc, SILValue selfPtr,
+                              SILDeclRef constant,
+                              CanSILFunctionType constantTy);
+
   /// Emit the specified VarDecl as an LValue if possible, otherwise return
   /// null.
   ManagedValue emitLValueForDecl(SILLocation loc, VarDecl *var,
@@ -1810,15 +1818,15 @@
 
 
 /// A utility class for saving and restoring the insertion point.
-class SavedInsertionPoint {
+class SILGenSavedInsertionPoint {
   SILGenFunction &SGF;
   SILBasicBlock *SavedIP;
   FunctionSection SavedSection;
 public:
-  SavedInsertionPoint(SILGenFunction &SGF, SILBasicBlock *newIP,
-                      Optional<FunctionSection> optSection = None)
-    : SGF(SGF), SavedIP(SGF.B.getInsertionBB()),
-      SavedSection(SGF.CurFunctionSection) {
+  SILGenSavedInsertionPoint(SILGenFunction &SGF, SILBasicBlock *newIP,
+                            Optional<FunctionSection> optSection = None)
+      : SGF(SGF), SavedIP(SGF.B.getInsertionBB()),
+        SavedSection(SGF.CurFunctionSection) {
     FunctionSection section = (optSection ? *optSection : SavedSection);
     assert((section != FunctionSection::Postmatter ||
             SGF.StartOfPostmatter != SGF.F.end()) &&
@@ -1829,10 +1837,11 @@
     SGF.CurFunctionSection = section;
   }
 
-  SavedInsertionPoint(const SavedInsertionPoint &) = delete;
-  SavedInsertionPoint &operator=(const SavedInsertionPoint &) = delete;
+  SILGenSavedInsertionPoint(const SILGenSavedInsertionPoint &) = delete;
+  SILGenSavedInsertionPoint &
+  operator=(const SILGenSavedInsertionPoint &) = delete;
 
-  ~SavedInsertionPoint() {
+  ~SILGenSavedInsertionPoint() {
     if (SavedIP) {
       SGF.B.setInsertionPoint(SavedIP);
     } else {
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index b0ccd080..859abba 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -1146,10 +1146,8 @@
 
       // If the declaration is in a different resilience domain, we have
       // to use materializeForSet.
-      //
-      // FIXME: Use correct ResilienceExpansion if SGF is @transparent
       if (!decl->hasFixedLayout(SGF.SGM.M.getSwiftModule(),
-                                ResilienceExpansion::Maximal))
+                                SGF.F.getResilienceExpansion()))
         return true;
 
       // If the declaration is dynamically dispatched through a class,
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 8c3e142..27910a1 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -1988,9 +1988,8 @@
       enumDecl = SGF.getASTContext().getOptionalDecl();
     }
 
-    // FIXME: Get expansion from SILFunction
     if (enumDecl->hasFixedLayout(SGF.SGM.M.getSwiftModule(),
-                                 ResilienceExpansion::Maximal)) {
+                                 SGF.F.getResilienceExpansion())) {
       exhaustive = true;
 
       for (auto elt : enumDecl->getAllElements()) {
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 4cd88e0..3a7fe53 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -60,8 +60,11 @@
 // Witness thunks
 // ==============
 //
-// Currently protocol witness methods are called with an additional generic
-// parameter bound to the Self type, and thus always require a thunk.
+// Protocol witness methods are called with an additional generic parameter
+// bound to the Self type, and thus always require a thunk. Thunks are also
+// required for conditional conformances, since the extra requirements aren't
+// part of the protocol and so any witness tables need to be loaded from the
+// original protocol's witness table and passed into the real witness method.
 //
 // Thunks for class method witnesses dispatch through the vtable allowing
 // inherited witnesses to be overridden in subclasses. Hence a witness thunk
@@ -2817,12 +2820,15 @@
       extInfo = extInfo.withIsPseudogeneric();
 
   // Add the function type as the parameter.
+  auto contextConvention = SGM.M.getOptions().EnableGuaranteedClosureContexts
+                               ? ParameterConvention::Direct_Guaranteed
+                               : DefaultThickCalleeConvention;
   SmallVector<SILParameterInfo, 4> params;
   params.append(expectedType->getParameters().begin(),
                 expectedType->getParameters().end());
   params.push_back({sourceType,
                     sourceType->getExtInfo().hasContext()
-                      ? DefaultThickCalleeConvention
+                      ? contextConvention
                       : ParameterConvention::Direct_Unowned});
 
   // Map the parameter and expected types out of context to get the interface
@@ -2837,6 +2843,15 @@
                        param.getConvention()));
   }
 
+  SmallVector<SILYieldInfo, 4> interfaceYields;
+  for (auto &yield : expectedType->getYields()) {
+    auto yieldIfaceTy = GenericEnvironment::mapTypeOutOfContext(
+        genericEnv, yield.getType());
+    auto interfaceYield =
+      yield.getWithType(yieldIfaceTy->getCanonicalType(genericSig));
+    interfaceYields.push_back(interfaceYield);
+  }
+
   SmallVector<SILResultInfo, 4> interfaceResults;
   for (auto &result : expectedType->getResults()) {
     auto resultIfaceTy = GenericEnvironment::mapTypeOutOfContext(
@@ -2858,9 +2873,10 @@
   
   // The type of the thunk function.
   return SILFunctionType::get(genericSig, extInfo,
+                              expectedType->getCoroutineKind(),
                               ParameterConvention::Direct_Unowned,
-                              interfaceParams, interfaceResults,
-                              interfaceErrorResult,
+                              interfaceParams, interfaceYields,
+                              interfaceResults, interfaceErrorResult,
                               getASTContext());
 }
 
@@ -2974,9 +2990,8 @@
   // Apply any ABI-compatible conversions before doing thin-to-thick.
   if (fnType != newFnType) {
     SILType resTy = SILType::getPrimitiveObjectType(newFnType);
-    fn = ManagedValue(
-        SGF.B.createConvertFunction(Loc, fn.getValue(), resTy),
-        fn.getCleanup());
+    fn = SGF.emitManagedRValueWithCleanup(
+        SGF.B.createConvertFunction(Loc, fn.forward(SGF), resTy));
   }
 
   // Now do thin-to-thick if necessary.
@@ -3274,9 +3289,7 @@
     return SGF.emitDynamicMethodRef(loc, witness, witnessFTy);
   case WitnessDispatchKind::Class: {
     SILValue selfPtr = witnessParams.back().getValue();
-    assert(!witness.isForeign);
-    return SGF.B.createClassMethod(loc, selfPtr, witness,
-                                   SILType::getPrimitiveObjectType(witnessFTy));
+    return SGF.emitClassMethodRef(loc, selfPtr, witness, witnessFTy);
   }
   }
 
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 87d6e2c..025443a 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -390,14 +390,20 @@
     SILType ty = lowering.getLoweredType();
     SILValue val = SGF.F.begin()->createFunctionArgument(ty, VD);
 
+    bool NeedToDestroyValueAtExit =
+        !SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts;
+
     // If the original variable was settable, then Sema will have treated the
     // VarDecl as an lvalue, even in the closure's use.  As such, we need to
     // allow formation of the address for this captured value.  Create a
     // temporary within the closure to provide this address.
     if (VD->isSettable(VD->getDeclContext())) {
       auto addr = SGF.emitTemporaryAllocation(VD, ty);
-      if (SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)
+      if (SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts) {
+        // We have created a copy that needs to be destroyed.
         val = SGF.B.createCopyValue(Loc, val);
+        NeedToDestroyValueAtExit = true;
+      }
       lowering.emitStore(SGF.B, VD, val, addr, StoreOwnershipQualifier::Init);
       val = addr;
     }
@@ -409,8 +415,7 @@
       SGF.B.createDebugValue(Loc, val, {/*Constant*/true, ArgNo});
 
     // TODO: Closure contexts should always be guaranteed.
-    if (!SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts
-        && !lowering.isTrivial())
+    if (NeedToDestroyValueAtExit && !lowering.isTrivial())
       SGF.enterDestroyCleanup(val);
     break;
   }
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index fd1e468..82953ae 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -550,7 +550,7 @@
     // Move the insertion point to the 'body' block temporarily and emit it.
     // Note that we don't push break/continue locations since they aren't valid
     // in this statement.
-    SavedInsertionPoint savedIP(SGF, bodyBB.getBlock());
+    SILGenSavedInsertionPoint savedIP(SGF, bodyBB.getBlock());
     SGF.emitProfilerIncrement(S->getBody());
     SGF.emitStmt(S->getBody());
 
@@ -691,7 +691,7 @@
   // has no predecessors, and SGF.ThrowDest may not be valid either.
   if (auto *BB = getOrEraseBlock(SGF, throwDest)) {
     // Move the insertion point to the throw destination.
-    SavedInsertionPoint savedIP(SGF, BB, FunctionSection::Postmatter);
+    SILGenSavedInsertionPoint savedIP(SGF, BB, FunctionSection::Postmatter);
 
     // The exception cleanup should be getting forwarded around
     // correctly anyway, but push a scope to ensure it gets popped.
@@ -976,7 +976,7 @@
                                            ValueOwnershipKind::Owned);
 
   assert(B.hasValidInsertionPoint() && B.insertingAtEndOfBlock());
-  SavedInsertionPoint savedIP(*this, destBB, FunctionSection::Postmatter);
+  SILGenSavedInsertionPoint savedIP(*this, destBB, FunctionSection::Postmatter);
 
   // If we're suppressing error paths, just wrap it up as unreachable
   // and return.
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index 6c56589..9429e09 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -33,11 +33,116 @@
 using namespace swift;
 using namespace Lowering;
 
+SILFunction *SILGenModule::getDispatchThunk(SILDeclRef constant,
+                                            ForDefinition_t forDefinition) {
+  // Mangle the constant with a Tv suffix.
+  auto name = constant.mangle(SILDeclRef::ManglingKind::SwiftDispatchThunk);
+  auto constantTy = M.Types.getConstantOverrideType(constant);
+
+  auto linkage = (forDefinition
+                  ? SILLinkage::Public
+                  : SILLinkage::PublicExternal);
+
+  // N.B.: Right now, we don't serialize vtables in resilient modules,
+  // so there's nothing to gain from marking these as serialized.
+  return M.getOrCreateFunction(constant.getDecl(), name, linkage,
+                               constantTy, IsBare, IsNotTransparent,
+                               IsNotSerialized, ProfileCounter(), IsThunk);
+}
+
+SILFunction *SILGenModule::emitDispatchThunk(SILDeclRef constant) {
+  auto *F = getDispatchThunk(constant, ForDefinition);
+
+  if (F->empty()) {
+    auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+
+    preEmitFunction(constant, afd, F, afd);
+    SILGenFunction SGF(*this, *F);
+    SGF.emitDispatchThunk(constant);
+    postEmitFunction(constant, F);
+  }
+
+  return F;
+}
+
+void SILGenFunction::emitDispatchThunk(SILDeclRef constant) {
+  auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+
+  SILLocation loc(afd);
+  loc.markAutoGenerated();
+
+  auto subs = F.getForwardingSubstitutions();
+
+  SmallVector<SILValue, 8> args;
+
+  // Add the indirect results.
+  for (auto resultTy : F.getConventions().getIndirectSILResultTypes()) {
+    auto paramTy = F.mapTypeIntoContext(resultTy);
+    args.push_back(F.begin()->createFunctionArgument(paramTy));
+  }
+
+  // Add the parameters.
+  auto paramTypes = F.getLoweredFunctionType()->getParameters();
+  for (auto param : paramTypes) {
+    auto paramTy = F.mapTypeIntoContext(F.getConventions().getSILType(param));
+    args.push_back(F.begin()->createFunctionArgument(paramTy));
+  }
+
+  auto constantTy = F.getLoweredFunctionType();
+
+  auto selfPtr = args.back();
+  auto fnValue =
+    B.createClassMethod(loc, selfPtr, constant,
+                        SILType::getPrimitiveObjectType(constantTy));
+  auto substFnType = fnValue->getType().substGenericArgs(SGM.M, subs);
+  auto result =
+    emitApplyWithRethrow(loc, fnValue, substFnType, subs, args);
+
+  B.createReturn(loc, result);
+}
+
+static bool shouldUseDispatchThunk(SILDeclRef constant,
+                                   SILFunction *F,
+                                   SILModule &M) {
+  auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+  auto *classDecl = cast<ClassDecl>(afd->getDeclContext());
+
+  // Resilient classes in other resilience domains use dispatch thunks.
+  return !classDecl->hasFixedLayout(M.getSwiftModule(),
+                                    F->getResilienceExpansion());
+}
+
+SILValue SILGenFunction::emitClassMethodRef(SILLocation loc,
+                                            SILValue selfPtr,
+                                            SILDeclRef constant,
+                                            CanSILFunctionType constantTy) {
+  assert(!constant.isForeign);
+
+  // Not every override gets a dispatch thunk; find the least derived one
+  // that does.
+  auto base = SGM.M.Types.getOverriddenVTableEntry(constant);
+
+  if (shouldUseDispatchThunk(base, &F, SGM.M)) {
+    auto *thunkFn = SGM.getDispatchThunk(base, NotForDefinition);
+
+    SILValue ref = B.createFunctionRef(loc, thunkFn);
+    if (thunkFn->getLoweredFunctionType() != constantTy) {
+      auto resultTy = SILType::getPrimitiveObjectType(constantTy);
+      ref = B.createConvertFunction(loc, ref, resultTy);
+    }
+
+    return ref;
+  }
+
+  return B.createClassMethod(loc, selfPtr, constant,
+                             SILType::getPrimitiveObjectType(constantTy));
+}
+
 SILFunction *SILGenModule::getDynamicThunk(SILDeclRef constant,
                                            CanSILFunctionType constantTy) {
   assert(constant.kind != SILDeclRef::Kind::Allocator &&
          "allocating entry point for constructor is never dynamic");
-  // Mangle the constant with a _TTD header.
+  // Mangle the constant with a TD suffix.
   auto name = constant.mangle(SILDeclRef::ManglingKind::DynamicThunk);
 
   auto F = M.getOrCreateFunction(constant.getDecl(), name, SILLinkage::Shared,
@@ -98,16 +203,11 @@
   if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
     if (getMethodDispatch(func) == MethodDispatch::Class) {
       // Use the dynamic thunk if dynamic.
-      if (vd->isDynamic()) {
-        auto dynamicThunk = SGF.SGM.getDynamicThunk(next,
-                                                    constantInfo.SILFnType);
-        return SGF.B.createFunctionRef(loc, dynamicThunk);
-      }
+      if (vd->isDynamic())
+        return SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType);
 
       auto methodTy = SGF.SGM.Types.getConstantOverrideType(next);
-      assert(!next.isForeign);
-      return SGF.B.createClassMethod(loc, selfArg, next,
-                                     SILType::getPrimitiveObjectType(methodTy));
+      return SGF.emitClassMethodRef(loc, selfArg, next, methodTy);
     }
 
     // If the fully-uncurried reference is to a generic method, look up the
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index 61bdb663..dbd8e4a 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -170,6 +170,7 @@
 public:
   SILGenModule &SGM;
   ClassDecl *theClass;
+  bool hasFixedLayout;
 
   // Map a base SILDeclRef to the corresponding element in vtableMethods.
   llvm::DenseMap<SILDeclRef, unsigned> baseToIndexMap;
@@ -178,8 +179,9 @@
   SmallVector<std::pair<SILDeclRef, SILDeclRef>, 8> vtableMethods;
 
   SILGenVTable(SILGenModule &SGM, ClassDecl *theClass)
-    : SILVTableVisitor(SGM.Types), SGM(SGM), theClass(theClass)
-  { }
+    : SILVTableVisitor(SGM.Types), SGM(SGM), theClass(theClass) {
+    hasFixedLayout = theClass->hasFixedLayout();
+  }
 
   void emitVTable() {
     // Imported types don't have vtables right now.
@@ -260,9 +262,21 @@
     auto result = baseToIndexMap.insert(std::make_pair(member, index));
     assert(result.second);
     (void) result;
+
+    // Emit a method dispatch thunk if the method is public and the
+    // class is resilient.
+    auto *func = cast<AbstractFunctionDecl>(member.getDecl());
+    if (func->getDeclContext() == theClass) {
+      if (!hasFixedLayout &&
+          func->getEffectiveAccess() >= AccessLevel::Public) {
+        SGM.emitDispatchThunk(member);
+      }
+    }
   }
 
-  void addPlaceholder(MissingMemberDecl *) {}
+  void addPlaceholder(MissingMemberDecl *) {
+    llvm_unreachable("Should not be emitting class with missing members");
+  }
 };
 
 } // end anonymous namespace
@@ -367,6 +381,7 @@
   SILGenModule &SGM;
   NormalProtocolConformance *Conformance;
   std::vector<SILWitnessTable::Entry> Entries;
+  std::vector<SILWitnessTable::ConditionalConformance> ConditionalConformances;
   SILLinkage Linkage;
   IsSerialized_t Serialized;
 
@@ -398,6 +413,8 @@
     auto *proto = Conformance->getProtocol();
     visitProtocolDecl(proto);
 
+    addConditionalRequirements();
+
     // Check if we already have a declaration or definition for this witness
     // table.
     if (auto *wt = SGM.M.lookUpWitnessTable(Conformance, false)) {
@@ -410,7 +427,7 @@
 
       // If we have a declaration, convert the witness table to a definition.
       if (wt->isDeclaration()) {
-        wt->convertToDefinition(Entries, Serialized);
+        wt->convertToDefinition(Entries, ConditionalConformances, Serialized);
 
         // Since we had a declaration before, its linkage should be external,
         // ensure that we have a compatible linkage for sanity. *NOTE* we are ok
@@ -427,8 +444,8 @@
     }
 
     // Otherwise if we have no witness table yet, create it.
-    return SILWitnessTable::create(SGM.M, Linkage, Serialized,
-                                   Conformance, Entries);
+    return SILWitnessTable::create(SGM.M, Linkage, Serialized, Conformance,
+                                   Entries, ConditionalConformances);
   }
 
   void addOutOfLineBaseProtocol(ProtocolDecl *baseProtocol) {
@@ -518,6 +535,22 @@
         req.getAssociation(), req.getAssociatedRequirement(),
         assocConformance});
   }
+
+  void addConditionalRequirements() {
+    SILWitnessTable::enumerateWitnessTableConditionalConformances(
+        Conformance, [&](unsigned, CanType type, ProtocolDecl *protocol) {
+          auto conformance =
+              Conformance->getGenericSignature()->lookupConformance(type,
+                                                                    protocol);
+          assert(conformance &&
+                 "unable to find conformance that should be known");
+
+          ConditionalConformances.push_back(
+              SILWitnessTable::ConditionalConformance{type, *conformance});
+
+          return /*finished?*/ false;
+        });
+  }
 };
 
 } // end anonymous namespace
diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp
index e4c2eed..f776571 100644
--- a/lib/SILOptimizer/ARC/ARCRegionState.cpp
+++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp
@@ -170,6 +170,8 @@
   // against the operand or can use the value in some way.
   case TermKind::ThrowInst:
   case TermKind::ReturnInst:
+  case TermKind::UnwindInst:
+  case TermKind::YieldInst:
   case TermKind::TryApplyInst:
   case TermKind::SwitchValueInst:
   case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
index bf3d1ae..50ae744 100644
--- a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
+++ b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
@@ -211,6 +211,8 @@
   // against the operand or can use the value in some way.
   case TermKind::ThrowInst:
   case TermKind::ReturnInst:
+  case TermKind::UnwindInst:
+  case TermKind::YieldInst:
   case TermKind::TryApplyInst:
   case TermKind::SwitchValueInst:
   case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 24cc25a..518cec2 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -84,16 +84,9 @@
       auto *AllocBufferAI = dyn_cast<ApplyInst>(Arg0);
       if (!AllocBufferAI)
         return false;
-
       auto *AllocFn = AllocBufferAI->getReferencedFunction();
-      if (!AllocFn)
-        return false;
-
-      StringRef AllocFuncName = AllocFn->getName();
-      if (AllocFuncName != "swift_bufferAllocate")
-        return false;
-
-      if (!hasOneNonDebugUse(AllocBufferAI))
+      if (!AllocFn || AllocFn->getName() != "swift_bufferAllocate" ||
+          !hasOneNonDebugUse(AllocBufferAI))
         return false;
     }
     return true;
diff --git a/lib/SILOptimizer/Analysis/CFG.cpp b/lib/SILOptimizer/Analysis/CFG.cpp
index ef1b825..e0e84de 100644
--- a/lib/SILOptimizer/Analysis/CFG.cpp
+++ b/lib/SILOptimizer/Analysis/CFG.cpp
@@ -34,6 +34,11 @@
   case TermKind::UnreachableInst:
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
+  case TermKind::UnwindInst:
+    return false;
+  // yield and try_apply are special because they can do arbitrary,
+  // potentially-process-terminating things.
+  case TermKind::YieldInst:
   case TermKind::TryApplyInst:
     return false;
   }
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 49b1c64..ddaacb2 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -416,7 +416,8 @@
   // Create the thin function type for the cloned closure.
   auto ClonedTy = SILFunctionType::get(
       OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
-      OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+      OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+      ClonedInterfaceArgTys, OrigFTI->getYields(),
       OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
       M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
 
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 5a0496e..ac5d62e 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -251,8 +251,9 @@
   // expressed as literals. So its callee signature will be the same as its
   // return signature.
   auto NewFTy = getPartialApplyInterfaceResultType(PAI);
-  NewFTy = Lowering::adjustFunctionType(NewFTy,
-                                        SILFunctionType::Representation::Thin);
+  NewFTy = Lowering::adjustFunctionType(
+      NewFTy, SILFunctionType::Representation::Thin,
+      OrigF->getModule().getOptions().EnableGuaranteedClosureContexts);
 
   GenericEnvironment *GenericEnv = nullptr;
   if (NewFTy->getGenericSignature())
@@ -404,6 +405,9 @@
   if (PAI->hasSubstitutions()) {
     if (Specialized->isExternalDeclaration())
       return nullptr;
+    if (!Orig->shouldOptimize())
+      return nullptr;
+
     // Perform a generic specialization of the Specialized function.
     ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
                              /* ConvertIndirectToDirect */ false);
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 73c0ff0..c21f9c9 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -614,8 +614,9 @@
 
   auto ClonedTy = SILFunctionType::get(
       ClosureUserFunTy->getGenericSignature(), ExtInfo,
+      ClosureUserFunTy->getCoroutineKind(),
       ClosureUserFunTy->getCalleeConvention(), NewParameterInfoList,
-      ClosureUserFunTy->getResults(),
+      ClosureUserFunTy->getYields(), ClosureUserFunTy->getResults(),
       ClosureUserFunTy->getOptionalErrorResult(), M.getASTContext());
 
   // We make this function bare so we don't have to worry about decls in the
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 51445c8..b12697f 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -208,6 +208,10 @@
       }
     }
 
+    for (const auto &conf : WT->getConditionalConformances()) {
+      if (conf.Conformance.isConcrete())
+        ensureAliveConformance(conf.Conformance.getConcrete());
+    }
   }
 
   /// Marks the declarations referenced by a key path pattern as alive if they
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 7de21a7..4d3581c 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -260,7 +260,8 @@
   SILFunctionType::ExtInfo EInfo;
   EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
   auto LoweredType = SILFunctionType::get(nullptr, EInfo,
-      ParameterConvention::Direct_Owned, { }, Results, None,
+      SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+      /*params*/ {}, /*yields*/ {}, Results, None,
       Store->getModule().getASTContext());
   auto *GetterF = Store->getModule().getOrCreateFunction(
       Store->getLoc(),
@@ -514,7 +515,8 @@
   SILFunctionType::ExtInfo EInfo;
   EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
   auto LoweredType = SILFunctionType::get(nullptr, EInfo,
-      ParameterConvention::Direct_Owned, { }, Results, None,
+      SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+      /*params*/ {}, /*yields*/ {}, Results, None,
       InitF->getASTContext());
   auto *GetterF = InitF->getModule().getOrCreateFunction(
       InitF->getLocation(),
diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
index b7267e7..70fd6da 100644
--- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
+++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
@@ -2316,8 +2316,7 @@
     auto *Fn = getFunction();
 
     // Don't hoist array property calls at Osize.
-    auto OptMode = Fn->getModule().getOptions().Optimization;
-    if (OptMode == SILOptions::SILOptMode::OptimizeForSize)
+    if (Fn->optimizeForSize())
       return;
 
     DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index 10e581c..f92c682 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -442,33 +442,56 @@
 }
 
 void SelectEnforcement::updateCapture(AddressCapture capture) {
+  auto captureIfEscaped = [&](SILInstruction *user) {
+    if (hasPotentiallyEscapedAt(user))
+      dynamicCaptures.recordCapture(capture);
+  };
   llvm::SmallSetVector<SingleValueInstruction *, 8> worklist;
   auto visitUse = [&](Operand *oper) {
     auto *user = oper->getUser();
     if (FullApplySite::isa(user)) {
       // A call is considered a closure access regardless of whether it calls
       // the closure or accepts the closure as an argument.
-      if (hasPotentiallyEscapedAt(user)) {
-        dynamicCaptures.recordCapture(capture);
-      }
+      captureIfEscaped(user);
       return;
     }
-    if (auto *CFI = dyn_cast<ConvertFunctionInst>(user)) {
-      worklist.insert(CFI);
+    switch (user->getKind()) {
+    case SILInstructionKind::ConvertFunctionInst:
+    case SILInstructionKind::BeginBorrowInst:
+    case SILInstructionKind::CopyValueInst:
+    case SILInstructionKind::EnumInst:
+    case SILInstructionKind::StructInst:
+    case SILInstructionKind::TupleInst:
+    case SILInstructionKind::PartialApplyInst:
+      // Propagate the closure.
+      worklist.insert(cast<SingleValueInstruction>(user));
       return;
-    }
-    if (auto *PAI = dyn_cast<PartialApplyInst>(user)) {
-      assert(oper->get() != PAI->getCallee() && "cannot re-partially apply");
-      // The closure is capture by another closure. Transitively consider any
-      // calls to the parent closure as an access.
-      worklist.insert(PAI);
+    case SILInstructionKind::StrongRetainInst:
+    case SILInstructionKind::StrongReleaseInst:
+    case SILInstructionKind::DebugValueInst:
+    case SILInstructionKind::DestroyValueInst:
+    case SILInstructionKind::RetainValueInst:
+    case SILInstructionKind::ReleaseValueInst:
+    case SILInstructionKind::EndBorrowInst:
+      // Benign use.
       return;
+    case SILInstructionKind::TupleExtractInst:
+    case SILInstructionKind::StructExtractInst:
+    case SILInstructionKind::AssignInst:
+    case SILInstructionKind::BranchInst:
+    case SILInstructionKind::CondBranchInst:
+    case SILInstructionKind::ReturnInst:
+    case SILInstructionKind::StoreInst:
+      // These are all valid partial_apply users, however we don't expect them
+      // to occur with non-escaping closures. Handle them conservatively just in
+      // case they occur.
+      LLVM_FALLTHROUGH;
+    default:
+      DEBUG(llvm::dbgs() << "    Unrecognized partial_apply user: " << *user);
+
+      // Handle unknown uses conservatively by assuming a capture.
+      captureIfEscaped(user);
     }
-    DEBUG(llvm::dbgs() << "    Unrecognized partial_apply user: " << *user);
-    // If this user has no results, then we can safely assume it doesn't pass
-    // the closure to a call site. If it has results, then it might propagate
-    // the closure, in which case it needs to be handled above.
-    assert(user->getResults().empty());
   };
   SingleValueInstruction *PAIUser = dyn_cast<PartialApplyInst>(capture.site);
   while (true) {
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index ff94b7e..7933b93 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -890,11 +890,13 @@
         continue;
 
       unsigned OperandNumber = OEAUse->getOperandNumber();
-      if (OperandNumber < 1 || OperandNumber > AI->getNumCallArguments())
+      auto OptArgumentNumber =
+        AI->getArgumentIndexForOperandIndex(OperandNumber);
+      if (!OptArgumentNumber)
         // Not used as a call argument
         continue;
 
-      unsigned ArgumentNumber = OperandNumber - 1;
+      unsigned ArgumentNumber = *OptArgumentNumber;
 
       CanSILFunctionType calleeType = AI->getSubstCalleeType();
       SILParameterInfo parameterInfo = calleeType->getParameters()[ArgumentNumber];
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index dd776f8..e24b67b 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -988,7 +988,7 @@
     // Check the closure's captures, which are a suffix of the closure's
     // parameters.
     unsigned StartIndex =
-        Closure->getArguments().size() - PAI->getNumCallArguments();
+        Closure->getArguments().size() - PAI->getNumArguments();
     checkForViolationWithCall(Accesses, Closure, StartIndex,
                               PAI->getArguments(), ASA, ConflictingAccesses);
   }
diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index 29aa4fe..1805c17 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -12,11 +12,12 @@
 
 #define DEBUG_TYPE "predictable-memopt"
 
-#include "swift/SILOptimizer/PassManager/Passes.h"
 #include "DIMemoryUseCollector.h"
 #include "swift/SIL/SILBuilder.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/PassManager/Passes.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/SILSSAUpdater.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
@@ -29,7 +30,7 @@
 STATISTIC(NumAllocRemoved, "Number of allocations completely removed");
 
 //===----------------------------------------------------------------------===//
-// Subelement Analysis Implementation
+//                            Subelement Analysis
 //===----------------------------------------------------------------------===//
 
 // We can only analyze components of structs whose storage is fully accessible
@@ -89,17 +90,16 @@
 /// This will return a subelement number of 2.
 ///
 /// If this pointer is to within an existential projection, it returns ~0U.
-///
 static unsigned computeSubelement(SILValue Pointer,
                                   SingleValueInstruction *RootInst) {
-  unsigned SubEltNumber = 0;
+  unsigned SubElementNumber = 0;
   SILModule &M = RootInst->getModule();
   
   while (1) {
     // If we got to the root, we're done.
     if (RootInst == Pointer)
-      return SubEltNumber;
-    
+      return SubElementNumber;
+
     if (auto *PBI = dyn_cast<ProjectBoxInst>(Pointer)) {
       Pointer = PBI->getOperand();
       continue;
@@ -115,7 +115,7 @@
       
       // Keep track of what subelement is being referenced.
       for (unsigned i = 0, e = TEAI->getFieldNo(); i != e; ++i) {
-        SubEltNumber += getNumSubElements(TT.getTupleElementType(i), M);
+        SubElementNumber += getNumSubElements(TT.getTupleElementType(i), M);
       }
       Pointer = TEAI->getOperand();
       continue;
@@ -128,7 +128,7 @@
       StructDecl *SD = SEAI->getStructDecl();
       for (auto *D : SD->getStoredProperties()) {
         if (D == SEAI->getField()) break;
-        SubEltNumber += getNumSubElements(ST.getFieldType(D, M), M);
+        SubElementNumber += getNumSubElements(ST.getFieldType(D, M), M);
       }
       
       Pointer = SEAI->getOperand();
@@ -143,14 +143,152 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+//                              Available Value
+//===----------------------------------------------------------------------===//
 
+namespace {
 
-/// Given an aggregate value and an access path, extract the value indicated by
-/// the path.
-static SILValue extractSubElement(SILValue Val, unsigned SubElementNumber,
-                                  SILBuilder &B, SILLocation Loc) {
-  SILType ValTy = Val->getType();
-  
+class AvailableValueAggregator;
+
+struct AvailableValue {
+  friend class AvailableValueAggregator;
+
+  /// If this gets too expensive in terms of copying, we can use an arena and a
+  /// FrozenPtrSet like we do in ARC.
+  using SetVector = llvm::SmallSetVector<SILInstruction *, 1>;
+
+  SILValue Value;
+  unsigned SubElementNumber;
+  SetVector InsertionPoints;
+
+  /// Just for updating.
+  SmallVectorImpl<DIMemoryUse> *Uses;
+
+public:
+  AvailableValue() = default;
+
+  /// Main initializer for available values.
+  ///
+  /// *NOTE* We assume that all available values start with a singular insertion
+  /// point and insertion points are added by merging.
+  AvailableValue(SILValue Value, unsigned SubElementNumber,
+                 SILInstruction *InsertPoint)
+      : Value(Value), SubElementNumber(SubElementNumber), InsertionPoints() {
+    InsertionPoints.insert(InsertPoint);
+  }
+
+  /// Deleted copy constructor. This is a move only type.
+  AvailableValue(const AvailableValue &) = delete;
+
+  /// Deleted copy operator. This is a move only type.
+  AvailableValue &operator=(const AvailableValue &) = delete;
+
+  /// Move constructor.
+  AvailableValue(AvailableValue &&Other)
+      : Value(nullptr), SubElementNumber(~0), InsertionPoints() {
+    std::swap(Value, Other.Value);
+    std::swap(SubElementNumber, Other.SubElementNumber);
+    std::swap(InsertionPoints, Other.InsertionPoints);
+  }
+
+  /// Move operator.
+  AvailableValue &operator=(AvailableValue &&Other) {
+    std::swap(Value, Other.Value);
+    std::swap(SubElementNumber, Other.SubElementNumber);
+    std::swap(InsertionPoints, Other.InsertionPoints);
+    return *this;
+  }
+
+  operator bool() const { return bool(Value); }
+
+  bool operator==(const AvailableValue &Other) const {
+    return Value == Other.Value && SubElementNumber == Other.SubElementNumber;
+  }
+
+  bool operator!=(const AvailableValue &Other) const {
+    return !(*this == Other);
+  }
+
+  SILValue getValue() const { return Value; }
+  SILType getType() const { return Value->getType(); }
+  unsigned getSubElementNumber() const { return SubElementNumber; }
+  ArrayRef<SILInstruction *> getInsertionPoints() const {
+    return InsertionPoints.getArrayRef();
+  }
+
+  void mergeInsertionPoints(const AvailableValue &Other) & {
+    assert(Value == Other.Value && SubElementNumber == Other.SubElementNumber);
+    InsertionPoints.set_union(Other.InsertionPoints);
+  }
+
+  void addInsertionPoint(SILInstruction *I) & { InsertionPoints.insert(I); }
+
+  /// TODO: This needs a better name.
+  AvailableValue emitStructExtract(SILBuilder &B, SILLocation Loc, VarDecl *D,
+                                   unsigned SubElementNumber) const {
+    SILValue NewValue = B.emitStructExtract(Loc, Value, D);
+    return {NewValue, SubElementNumber, InsertionPoints};
+  }
+
+  /// TODO: This needs a better name.
+  AvailableValue emitTupleExtract(SILBuilder &B, SILLocation Loc,
+                                  unsigned EltNo,
+                                  unsigned SubElementNumber) const {
+    SILValue NewValue = B.emitTupleExtract(Loc, Value, EltNo);
+    return {NewValue, SubElementNumber, InsertionPoints};
+  }
+
+  void dump() const __attribute__((used));
+  void print(llvm::raw_ostream &os) const;
+
+private:
+  /// Private constructor.
+  AvailableValue(SILValue Value, unsigned SubElementNumber,
+                 const SetVector &InsertPoints)
+      : Value(Value), SubElementNumber(SubElementNumber),
+        InsertionPoints(InsertPoints) {}
+};
+
+} // end anonymous namespace
+
+void AvailableValue::dump() const { print(llvm::dbgs()); }
+
+void AvailableValue::print(llvm::raw_ostream &os) const {
+  os << "Available Value Dump. Value: ";
+  if (getValue()) {
+    os << getValue();
+  } else {
+    os << "NoValue;\n";
+  }
+  os << "SubElementNumber: " << getSubElementNumber() << "\n";
+  os << "Insertion Points:\n";
+  for (auto *I : getInsertionPoints()) {
+    os << *I;
+  }
+}
+
+namespace llvm {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const AvailableValue &V) {
+  V.print(os);
+  return os;
+}
+
+} // end llvm namespace
+
+//===----------------------------------------------------------------------===//
+//                           Subelement Extraction
+//===----------------------------------------------------------------------===//
+
+/// Given an aggregate value and an access path, non-destructively extract the
+/// value indicated by the path.
+static SILValue nonDestructivelyExtractSubElement(const AvailableValue &Val,
+                                                  SILBuilder &B,
+                                                  SILLocation Loc) {
+  SILType ValTy = Val.getType();
+  unsigned SubElementNumber = Val.SubElementNumber;
+
   // Extract tuple elements.
   if (auto TT = ValTy.getAs<TupleType>()) {
     for (unsigned EltNo : indices(TT.getElementTypes())) {
@@ -158,8 +296,8 @@
       SILType EltTy = ValTy.getTupleElementType(EltNo);
       unsigned NumSubElt = getNumSubElements(EltTy, B.getModule());
       if (SubElementNumber < NumSubElt) {
-        Val = B.emitTupleExtract(Loc, Val, EltNo, EltTy);
-        return extractSubElement(Val, SubElementNumber, B, Loc);
+        auto NewVal = Val.emitTupleExtract(B, Loc, EltNo, SubElementNumber);
+        return nonDestructivelyExtractSubElement(NewVal, B, Loc);
       }
       
       SubElementNumber -= NumSubElt;
@@ -175,8 +313,8 @@
       unsigned NumSubElt = getNumSubElements(fieldType, B.getModule());
       
       if (SubElementNumber < NumSubElt) {
-        Val = B.emitStructExtract(Loc, Val, D);
-        return extractSubElement(Val, SubElementNumber, B, Loc);
+        auto NewVal = Val.emitStructExtract(B, Loc, D, SubElementNumber);
+        return nonDestructivelyExtractSubElement(NewVal, B, Loc);
       }
       
       SubElementNumber -= NumSubElt;
@@ -187,109 +325,314 @@
   
   // Otherwise, we're down to a scalar.
   assert(SubElementNumber == 0 && "Miscalculation indexing subelements");
-  return Val;
+  return Val.getValue();
 }
 
 //===----------------------------------------------------------------------===//
-//                          Allocation Optimization
+//                        Available Value Aggregation
+//===----------------------------------------------------------------------===//
+
+static bool anyMissing(unsigned StartSubElt, unsigned NumSubElts,
+                       ArrayRef<AvailableValue> &Values) {
+  while (NumSubElts) {
+    if (!Values[StartSubElt])
+      return true;
+    ++StartSubElt;
+    --NumSubElts;
+  }
+  return false;
+}
+
+namespace {
+
+/// A class that aggregates available values, loading them if they are not
+/// available.
+class AvailableValueAggregator {
+  SILModule &M;
+  SILBuilderWithScope B;
+  SILLocation Loc;
+  MutableArrayRef<AvailableValue> AvailableValueList;
+  SmallVectorImpl<DIMemoryUse> &Uses;
+
+public:
+  AvailableValueAggregator(SILInstruction *Inst,
+                           MutableArrayRef<AvailableValue> AvailableValueList,
+                           SmallVectorImpl<DIMemoryUse> &Uses)
+      : M(Inst->getModule()), B(Inst), Loc(Inst->getLoc()),
+        AvailableValueList(AvailableValueList), Uses(Uses) {}
+
+  // This is intended to be passed by reference only once constructed.
+  AvailableValueAggregator(const AvailableValueAggregator &) = delete;
+  AvailableValueAggregator(AvailableValueAggregator &&) = delete;
+  AvailableValueAggregator &
+  operator=(const AvailableValueAggregator &) = delete;
+  AvailableValueAggregator &operator=(AvailableValueAggregator &&) = delete;
+
+  SILValue aggregateValues(SILType LoadTy, SILValue Address, unsigned FirstElt);
+
+  void print(llvm::raw_ostream &os) const;
+  void dump() const __attribute__((used));
+
+private:
+  SILValue aggregateFullyAvailableValue(SILType LoadTy, unsigned FirstElt);
+  SILValue aggregateTupleSubElts(TupleType *TT, SILType LoadTy,
+                                 SILValue Address, unsigned FirstElt);
+  SILValue aggregateStructSubElts(StructDecl *SD, SILType LoadTy,
+                                  SILValue Address, unsigned FirstElt);
+  SILValue handlePrimitiveValue(SILType LoadTy, SILValue Address,
+                                unsigned FirstElt);
+};
+
+} // end anonymous namespace
+
+void AvailableValueAggregator::dump() const { print(llvm::dbgs()); }
+
+void AvailableValueAggregator::print(llvm::raw_ostream &os) const {
+  os << "Available Value List, N = " << AvailableValueList.size()
+     << ". Elts:\n";
+  for (auto &V : AvailableValueList) {
+    os << V;
+  }
+}
+
+/// Given a bunch of primitive subelement values, build out the right aggregate
+/// type (LoadTy) by emitting tuple and struct instructions as necessary.
+SILValue AvailableValueAggregator::aggregateValues(SILType LoadTy,
+                                                   SILValue Address,
+                                                   unsigned FirstElt) {
+  // Check to see if the requested value is fully available, as an aggregate.
+  // This is a super-common case for single-element structs, but is also a
+  // general answer for arbitrary structs and tuples as well.
+  if (SILValue Result = aggregateFullyAvailableValue(LoadTy, FirstElt))
+    return Result;
+
+  // If we have a tuple type, then aggregate the tuple's elements into a full
+  // tuple value.
+  if (TupleType *TT = LoadTy.getAs<TupleType>())
+    return aggregateTupleSubElts(TT, LoadTy, Address, FirstElt);
+
+  // If we have a struct type, then aggregate the struct's elements into a full
+  // struct value.
+  if (auto *SD = getFullyReferenceableStruct(LoadTy))
+    return aggregateStructSubElts(SD, LoadTy, Address, FirstElt);
+
+  // Otherwise, we have a non-aggregate primitive. Load or extract the value.
+  return handlePrimitiveValue(LoadTy, Address, FirstElt);
+}
+
+// See if we have this value is fully available. In such a case, return it as an
+// aggregate. This is a super-common case for single-element structs, but is
+// also a general answer for arbitrary structs and tuples as well.
+SILValue
+AvailableValueAggregator::aggregateFullyAvailableValue(SILType LoadTy,
+                                                       unsigned FirstElt) {
+  if (FirstElt >= AvailableValueList.size()) { // #Elements may be zero.
+    return SILValue();
+  }
+
+  auto &FirstVal = AvailableValueList[FirstElt];
+
+  // Make sure that the first element is available and is the correct type.
+  if (!FirstVal || FirstVal.getType() != LoadTy)
+    return SILValue();
+
+  // If the first element of this value is available, check that any extra
+  // available values are from the same place as our first value.
+  if (llvm::any_of(range(getNumSubElements(LoadTy, M)),
+                   [&](unsigned Index) -> bool {
+                     auto &Val = AvailableValueList[FirstElt + Index];
+                     return Val.getValue() != FirstVal.getValue() ||
+                            Val.getSubElementNumber() != Index;
+                   }))
+    return SILValue();
+
+  return FirstVal.getValue();
+}
+
+SILValue AvailableValueAggregator::aggregateTupleSubElts(TupleType *TT,
+                                                         SILType LoadTy,
+                                                         SILValue Address,
+                                                         unsigned FirstElt) {
+  SmallVector<SILValue, 4> ResultElts;
+
+  for (unsigned EltNo : indices(TT->getElements())) {
+    SILType EltTy = LoadTy.getTupleElementType(EltNo);
+    unsigned NumSubElt = getNumSubElements(EltTy, M);
+
+    // If we are missing any of the available values in this struct element,
+    // compute an address to load from.
+    SILValue EltAddr;
+    if (anyMissing(FirstElt, NumSubElt, AvailableValueList))
+      EltAddr =
+          B.createTupleElementAddr(Loc, Address, EltNo, EltTy.getAddressType());
+
+    ResultElts.push_back(aggregateValues(EltTy, EltAddr, FirstElt));
+    FirstElt += NumSubElt;
+  }
+
+  return B.createTuple(Loc, LoadTy, ResultElts);
+}
+
+SILValue AvailableValueAggregator::aggregateStructSubElts(StructDecl *SD,
+                                                          SILType LoadTy,
+                                                          SILValue Address,
+                                                          unsigned FirstElt) {
+  SmallVector<SILValue, 4> ResultElts;
+
+  for (auto *FD : SD->getStoredProperties()) {
+    SILType EltTy = LoadTy.getFieldType(FD, M);
+    unsigned NumSubElt = getNumSubElements(EltTy, M);
+
+    // If we are missing any of the available values in this struct element,
+    // compute an address to load from.
+    SILValue EltAddr;
+    if (anyMissing(FirstElt, NumSubElt, AvailableValueList))
+      EltAddr =
+          B.createStructElementAddr(Loc, Address, FD, EltTy.getAddressType());
+
+    ResultElts.push_back(aggregateValues(EltTy, EltAddr, FirstElt));
+    FirstElt += NumSubElt;
+  }
+  return B.createStruct(Loc, LoadTy, ResultElts);
+}
+
+// We have looked through all of the aggregate values and finally found a
+// "primitive value". If the value is available, use it (extracting if we need
+// to), otherwise emit a load of the value with the appropriate qualifier.
+SILValue AvailableValueAggregator::handlePrimitiveValue(SILType LoadTy,
+                                                        SILValue Address,
+                                                        unsigned FirstElt) {
+  auto &Val = AvailableValueList[FirstElt];
+
+  // If the value is not available, load the value and update our use list.
+  if (!Val) {
+    auto *Load =
+        B.createLoad(Loc, Address, LoadOwnershipQualifier::Unqualified);
+    Uses.push_back(DIMemoryUse(Load, DIUseKind::Load, FirstElt,
+                               getNumSubElements(Load->getType(), M)));
+    return Load;
+  }
+
+  // If we have 1 insertion point, just extract the value and return.
+  //
+  // This saves us from having to spend compile time in the SSA updater in this
+  // case.
+  ArrayRef<SILInstruction *> InsertPts = Val.getInsertionPoints();
+  if (InsertPts.size() == 1) {
+    SavedInsertionPointRAII SavedInsertPt(B, InsertPts[0]);
+    SILValue EltVal = nonDestructivelyExtractSubElement(Val, B, Loc);
+    assert(EltVal->getType() == LoadTy && "Subelement types mismatch");
+    return EltVal;
+  }
+
+  // If we have an available value, then we want to extract the subelement from
+  // the borrowed aggregate before each insertion point.
+  SILSSAUpdater Updater;
+  Updater.Initialize(LoadTy);
+  for (auto *I : Val.getInsertionPoints()) {
+    SavedInsertionPointRAII SavedInsertPt(B, I);
+    SILValue EltVal = nonDestructivelyExtractSubElement(Val, B, Loc);
+    Updater.AddAvailableValue(I->getParent(), EltVal);
+  }
+
+  // Finally, grab the value from the SSA updater.
+  SILValue EltVal = Updater.GetValueInMiddleOfBlock(B.getInsertionBB());
+  assert(EltVal->getType() == LoadTy && "Subelement types mismatch");
+  return EltVal;
+}
+
+//===----------------------------------------------------------------------===//
+//                          Available Value Dataflow
 //===----------------------------------------------------------------------===//
 
 namespace {
 
-/// This performs load promotion and deletes synthesized allocations if all
-/// loads can be removed.
-class AllocOptimize {
-
-  SILModule &Module;
-
-  /// This is either an alloc_box or alloc_stack instruction.
+/// Given a piece of memory, the memory's uses, and destroys perform a single
+/// round of optimistic dataflow switching to intersection when a back edge is
+/// encountered.
+class AvailableValueDataflowContext {
+  /// The base memory we are performing dataflow upon.
   AllocationInst *TheMemory;
 
-  /// This is the SILType of the memory object.
-  SILType MemoryType;
-
-  /// The number of primitive subelements across all elements of this memory
-  /// value.
+  /// The number of sub elements of our memory.
   unsigned NumMemorySubElements;
 
-  SmallVectorImpl<DIMemoryUse> &Uses;
-  SmallVectorImpl<SILInstruction *> &Releases;
+  /// The set of uses that we are tracking. This is only here so we can update
+  /// when exploding copy_addr. It would be great if we did not have to store
+  /// this.
+  llvm::SmallVectorImpl<DIMemoryUse> &Uses;
 
+  /// The set of blocks with local definitions.
+  ///
+  /// We use this to determine if we should visit a block or look at a block's
+  /// predecessors during dataflow.
   llvm::SmallPtrSet<SILBasicBlock *, 32> HasLocalDefinition;
 
   /// This is a map of uses that are not loads (i.e., they are Stores,
   /// InOutUses, and Escapes), to their entry in Uses.
   llvm::SmallDenseMap<SILInstruction *, unsigned, 16> NonLoadUses;
 
-  /// Does this value escape anywhere in the function.
+  /// Does this value escape anywhere in the function. We use this very
+  /// conservatively.
   bool HasAnyEscape = false;
 
 public:
-  AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
-                SmallVectorImpl<SILInstruction *> &Releases);
+  AvailableValueDataflowContext(AllocationInst *TheMemory,
+                                unsigned NumMemorySubElements,
+                                llvm::SmallVectorImpl<DIMemoryUse> &Uses);
 
-  bool doIt();
+  /// Try to compute available values for "TheMemory" at the instruction \p
+  /// StartingFrom. We only compute the values for set bits in \p
+  /// RequiredElts. We return the vailable values in \p Result. If any available
+  /// values were found, return true. Otherwise, return false.
+  bool computeAvailableValues(SILInstruction *StartingFrom,
+                              unsigned FirstEltOffset,
+                              unsigned NumLoadSubElements,
+                              llvm::SmallBitVector &RequiredElts,
+                              SmallVectorImpl<AvailableValue> &Result);
+
+  /// Return true if the box has escaped at the specified instruction.  We are
+  /// not
+  /// allowed to do load promotion in an escape region.
+  bool hasEscapedAt(SILInstruction *I);
+
+  /// Explode a copy_addr, updating the Uses at the same time.
+  void explodeCopyAddr(CopyAddrInst *CAI);
 
 private:
-  bool promoteLoad(SILInstruction *Inst);
-  bool promoteDestroyAddr(DestroyAddrInst *DAI);
+  SILModule &getModule() const { return TheMemory->getModule(); }
 
-  // Load promotion.
-  bool hasEscapedAt(SILInstruction *I);
-  void
-  updateAvailableValues(SILInstruction *Inst,
-                        llvm::SmallBitVector &RequiredElts,
-                        SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
-                        llvm::SmallBitVector &ConflictingValues);
-  void computeAvailableValues(
-      SILInstruction *StartingFrom, llvm::SmallBitVector &RequiredElts,
-      SmallVectorImpl<std::pair<SILValue, unsigned>> &Result);
+  void updateAvailableValues(SILInstruction *Inst,
+                             llvm::SmallBitVector &RequiredElts,
+                             SmallVectorImpl<AvailableValue> &Result,
+                             llvm::SmallBitVector &ConflictingValues);
   void computeAvailableValuesFrom(
       SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
       llvm::SmallBitVector &RequiredElts,
-      SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
+      SmallVectorImpl<AvailableValue> &Result,
       llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
           &VisitedBlocks,
       llvm::SmallBitVector &ConflictingValues);
-
-  void explodeCopyAddr(CopyAddrInst *CAI);
-
-  bool tryToRemoveDeadAllocation();
 };
 
 } // end anonymous namespace
 
-
-AllocOptimize::AllocOptimize(AllocationInst *TheMemory,
-                             SmallVectorImpl<DIMemoryUse> &Uses,
-                             SmallVectorImpl<SILInstruction*> &Releases)
-: Module(TheMemory->getModule()), TheMemory(TheMemory), Uses(Uses),
-  Releases(Releases) {
-  
-  // Compute the type of the memory object.
-  if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
-    assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
-           && "optimizing multi-field boxes not implemented");
-    MemoryType = ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
-  } else {
-    assert(isa<AllocStackInst>(TheMemory));
-    MemoryType = cast<AllocStackInst>(TheMemory)->getElementType();
-  }
-  
-  NumMemorySubElements = getNumSubElements(MemoryType, Module);
-  
+AvailableValueDataflowContext::AvailableValueDataflowContext(
+    AllocationInst *InputTheMemory, unsigned NumMemorySubElements,
+    SmallVectorImpl<DIMemoryUse> &InputUses)
+    : TheMemory(InputTheMemory), NumMemorySubElements(NumMemorySubElements),
+      Uses(InputUses) {
   // The first step of processing an element is to collect information about the
   // element into data structures we use later.
-  for (unsigned ui = 0, e = Uses.size(); ui != e; ++ui) {
+  for (unsigned ui : indices(Uses)) {
     auto &Use = Uses[ui];
     assert(Use.Inst && "No instruction identified?");
-    
+
     // Keep track of all the uses that aren't loads.
     if (Use.Kind == DIUseKind::Load)
       continue;
-    
+
     NonLoadUses[Use.Inst] = ui;
-    
     HasLocalDefinition.insert(Use.Inst->getParent());
     
     if (Use.Kind == DIUseKind::Escape) {
@@ -305,34 +648,18 @@
   HasLocalDefinition.insert(TheMemory->getParent());
 }
 
-
-/// hasEscapedAt - Return true if the box has escaped at the specified
-/// instruction.  We are not allowed to do load promotion in an escape region.
-bool AllocOptimize::hasEscapedAt(SILInstruction *I) {
-  // FIXME: This is not an aggressive implementation.  :)
-  
-  // TODO: At some point, we should special case closures that just *read* from
-  // the escaped value (by looking at the body of the closure).  They should not
-  // prevent load promotion, and will allow promoting values like X in regions
-  // dominated by "... && X != 0".
-  return HasAnyEscape;
-}
-
-
-/// The specified instruction is a non-load access of the element being
-/// promoted.  See if it provides a value or refines the demanded element mask
-/// used for load promotion.
-void AllocOptimize::
-updateAvailableValues(SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
-                      SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
-                      llvm::SmallBitVector &ConflictingValues) {
-  // Handle store and assign.
-  if (isa<StoreInst>(Inst)) {
-    unsigned StartSubElt = computeSubelement(Inst->getOperand(1), TheMemory);
+void AvailableValueDataflowContext::updateAvailableValues(
+    SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
+    SmallVectorImpl<AvailableValue> &Result,
+    llvm::SmallBitVector &ConflictingValues) {
+  // Handle store.
+  if (auto *SI = dyn_cast<StoreInst>(Inst)) {
+    unsigned StartSubElt = computeSubelement(SI->getDest(), TheMemory);
     assert(StartSubElt != ~0U && "Store within enum projection not handled");
-    SILType ValTy = Inst->getOperand(0)->getType();
-    
-    for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+    SILType ValTy = SI->getSrc()->getType();
+
+    for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+         ++i) {
       // If this element is not required, don't fill it in.
       if (!RequiredElts[StartSubElt+i]) continue;
       
@@ -340,11 +667,19 @@
       // there already is a result, check it for conflict.  If there is no
       // conflict, then we're ok.
       auto &Entry = Result[StartSubElt+i];
-      if (Entry.first == SILValue())
-        Entry = { Inst->getOperand(0), i };
-      else if (Entry.first != Inst->getOperand(0) || Entry.second != i)
-        ConflictingValues[StartSubElt+i] = true;
-      
+      if (!Entry) {
+        Entry = {SI->getSrc(), i, Inst};
+      } else {
+        // TODO: This is /really/, /really/, conservative. This basically means
+        // that if we do not have an identical store, we will not promote.
+        if (Entry.getValue() != SI->getSrc() ||
+            Entry.getSubElementNumber() != i) {
+          ConflictingValues[StartSubElt + i] = true;
+        } else {
+          Entry.addInsertionPoint(Inst);
+        }
+      }
+
       // This element is now provided.
       RequiredElts[StartSubElt+i] = false;
     }
@@ -356,12 +691,13 @@
   // to see if any loaded subelements are being used, and if so, explode the
   // copy_addr to its individual pieces.
   if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
-    unsigned StartSubElt = computeSubelement(Inst->getOperand(1), TheMemory);
+    unsigned StartSubElt = computeSubelement(CAI->getDest(), TheMemory);
     assert(StartSubElt != ~0U && "Store within enum projection not handled");
-    SILType ValTy = Inst->getOperand(1)->getType();
-    
+    SILType ValTy = CAI->getDest()->getType();
+
     bool AnyRequired = false;
-    for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+    for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+         ++i) {
       // If this element is not required, don't fill it in.
       AnyRequired = RequiredElts[StartSubElt+i];
       if (AnyRequired) break;
@@ -374,7 +710,7 @@
     
     // If the copyaddr is of a non-loadable type, we can't promote it.  Just
     // consider it to be a clobber.
-    if (CAI->getOperand(0)->getType().isLoadable(Module)) {
+    if (CAI->getSrc()->getType().isLoadable(getModule())) {
       // Otherwise, some part of the copy_addr's value is demanded by a load, so
       // we need to explode it to its component pieces.  This only expands one
       // level of the copyaddr.
@@ -385,11 +721,9 @@
       return;
     }
   }
-  
-  
-  
+
   // TODO: inout apply's should only clobber pieces passed in.
-  
+
   // Otherwise, this is some unknown instruction, conservatively assume that all
   // values are clobbered.
   RequiredElts.clear();
@@ -397,42 +731,59 @@
   return;
 }
 
-
-/// Try to find available values of a set of subelements of the current value,
-/// starting right before the specified instruction.
-///
-/// The bitvector indicates which subelements we're interested in, and result
-/// captures the available value (plus an indicator of which subelement of that
-/// value is needed).
-///
-void AllocOptimize::
-computeAvailableValues(SILInstruction *StartingFrom,
-                       llvm::SmallBitVector &RequiredElts,
-                       SmallVectorImpl<std::pair<SILValue, unsigned>> &Result) {
+bool AvailableValueDataflowContext::computeAvailableValues(
+    SILInstruction *StartingFrom, unsigned FirstEltOffset,
+    unsigned NumLoadSubElements, llvm::SmallBitVector &RequiredElts,
+    SmallVectorImpl<AvailableValue> &Result) {
   llvm::SmallDenseMap<SILBasicBlock*, llvm::SmallBitVector, 32> VisitedBlocks;
   llvm::SmallBitVector ConflictingValues(Result.size());
 
   computeAvailableValuesFrom(StartingFrom->getIterator(),
                              StartingFrom->getParent(), RequiredElts, Result,
                              VisitedBlocks, ConflictingValues);
+  // If there are no values available at this load point, then we fail to
+  // promote this load and there is nothing to do.
+  llvm::SmallBitVector AvailableValueIsPresent(NumMemorySubElements);
 
-  // If we have any conflicting values, explicitly mask them out of the result,
-  // so we don't pick one arbitrary available value.
-  if (!ConflictingValues.none())
-    for (unsigned i = 0, e = Result.size(); i != e; ++i)
-      if (ConflictingValues[i])
-        Result[i] = { SILValue(), 0U };
-  
-  return;
+  for (unsigned i :
+       range(FirstEltOffset, FirstEltOffset + NumLoadSubElements)) {
+    AvailableValueIsPresent[i] = Result[i].getValue();
+  }
+
+  // If we do not have any values available, bail.
+  if (AvailableValueIsPresent.none())
+    return false;
+
+  // Otherwise, if we have any conflicting values, explicitly mask them out of
+  // the result, so we don't pick one arbitrary available value.
+  if (ConflictingValues.none()) {
+    return true;
+  }
+
+  // At this point, we know that we have /some/ conflicting values and some
+  // available values.
+  if (AvailableValueIsPresent.reset(ConflictingValues).none())
+    return false;
+
+  // Otherwise, mask out the available values and return true. We have at least
+  // 1 available value.
+  int NextIter = ConflictingValues.find_first();
+  while (NextIter != -1) {
+    assert(NextIter >= 0 && "Int can not be represented?!");
+    unsigned Iter = NextIter;
+    Result[Iter] = {};
+    NextIter = ConflictingValues.find_next(Iter);
+  }
+
+  return true;
 }
 
-void AllocOptimize::
-computeAvailableValuesFrom(SILBasicBlock::iterator StartingFrom,
-                           SILBasicBlock *BB,
-                           llvm::SmallBitVector &RequiredElts,
-                         SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
-   llvm::SmallDenseMap<SILBasicBlock*, llvm::SmallBitVector, 32> &VisitedBlocks,
-                           llvm::SmallBitVector &ConflictingValues) {
+void AvailableValueDataflowContext::computeAvailableValuesFrom(
+    SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
+    llvm::SmallBitVector &RequiredElts, SmallVectorImpl<AvailableValue> &Result,
+    llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
+        &VisitedBlocks,
+    llvm::SmallBitVector &ConflictingValues) {
   assert(!RequiredElts.none() && "Scanning with a goal of finding nothing?");
   
   // If there is a potential modification in the current block, scan the block
@@ -501,111 +852,202 @@
   }
 }
 
+/// Explode a copy_addr instruction of a loadable type into lower level
+/// operations like loads, stores, retains, releases, retain_value, etc.
+void AvailableValueDataflowContext::explodeCopyAddr(CopyAddrInst *CAI) {
+  DEBUG(llvm::dbgs() << "  -- Exploding copy_addr: " << *CAI << "\n");
 
-static bool anyMissing(unsigned StartSubElt, unsigned NumSubElts,
-                       ArrayRef<std::pair<SILValue, unsigned>> &Values) {
-  while (NumSubElts) {
-    if (!Values[StartSubElt].first) return true;
-    ++StartSubElt;
-    --NumSubElts;
+  SILType ValTy = CAI->getDest()->getType().getObjectType();
+  auto &TL = getModule().getTypeLowering(ValTy);
+
+  // Keep track of the new instructions emitted.
+  SmallVector<SILInstruction *, 4> NewInsts;
+  SILBuilder B(CAI, &NewInsts);
+  B.setCurrentDebugScope(CAI->getDebugScope());
+
+  // Use type lowering to lower the copyaddr into a load sequence + store
+  // sequence appropriate for the type.
+  SILValue StoredValue =
+      TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(), CAI->isTakeOfSrc());
+
+  TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
+                     CAI->isInitializationOfDest());
+
+  // Update our internal state for this being gone.
+  NonLoadUses.erase(CAI);
+
+  // Remove the copy_addr from Uses.  A single copy_addr can appear multiple
+  // times if the source and dest are to elements within a single aggregate, but
+  // we only want to pick up the CopyAddrKind from the store.
+  DIMemoryUse LoadUse, StoreUse;
+  for (auto &Use : Uses) {
+    if (Use.Inst != CAI)
+      continue;
+
+    if (Use.Kind == DIUseKind::Load) {
+      assert(LoadUse.isInvalid());
+      LoadUse = Use;
+    } else {
+      assert(StoreUse.isInvalid());
+      StoreUse = Use;
+    }
+
+    Use.Inst = nullptr;
+
+    // Keep scanning in case the copy_addr appears multiple times.
   }
-  return false;
+
+  assert((LoadUse.isValid() || StoreUse.isValid()) &&
+         "we should have a load or a store, possibly both");
+  assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
+         StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
+
+  // Now that we've emitted a bunch of instructions, including a load and store
+  // but also including other stuff, update the internal state of
+  // LifetimeChecker to reflect them.
+
+  // Update the instructions that touch the memory.  NewInst can grow as this
+  // iterates, so we can't use a foreach loop.
+  for (auto *NewInst : NewInsts) {
+    switch (NewInst->getKind()) {
+    default:
+      NewInst->dump();
+      llvm_unreachable("Unknown instruction generated by copy_addr lowering");
+
+    case SILInstructionKind::StoreInst:
+      // If it is a store to the memory object (as oppose to a store to
+      // something else), track it as an access.
+      if (StoreUse.isValid()) {
+        StoreUse.Inst = NewInst;
+        NonLoadUses[NewInst] = Uses.size();
+        Uses.push_back(StoreUse);
+      }
+      continue;
+
+    case SILInstructionKind::LoadInst:
+      // If it is a load from the memory object (as oppose to a load from
+      // something else), track it as an access.  We need to explicitly check to
+      // see if the load accesses "TheMemory" because it could either be a load
+      // for the copy_addr source, or it could be a load corresponding to the
+      // "assign" operation on the destination of the copyaddr.
+      if (LoadUse.isValid() &&
+          getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
+        LoadUse.Inst = NewInst;
+        Uses.push_back(LoadUse);
+      }
+      continue;
+
+    case SILInstructionKind::RetainValueInst:
+    case SILInstructionKind::StrongRetainInst:
+    case SILInstructionKind::StrongReleaseInst:
+    case SILInstructionKind::UnownedRetainInst:
+    case SILInstructionKind::UnownedReleaseInst:
+    case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
+      // These are ignored.
+      continue;
+    }
+  }
+
+  // Next, remove the copy_addr itself.
+  CAI->eraseFromParent();
 }
 
+bool AvailableValueDataflowContext::hasEscapedAt(SILInstruction *I) {
+  // Return true if the box has escaped at the specified instruction.  We are
+  // not allowed to do load promotion in an escape region.
 
-/// AggregateAvailableValues - Given a bunch of primitive subelement values,
-/// build out the right aggregate type (LoadTy) by emitting tuple and struct
-/// instructions as necessary.
-static SILValue aggregateAvailableValues(
-    SILInstruction *Inst, SILType LoadTy, SILValue Address,
-    ArrayRef<std::pair<SILValue, unsigned>> AvailableValues,
-    unsigned FirstElt) {
-  assert(LoadTy.isObject());
-  SILModule &M = Inst->getModule();
-  
-  // Check to see if the requested value is fully available, as an aggregate.
-  // This is a super-common case for single-element structs, but is also a
-  // general answer for arbitrary structs and tuples as well.
-  if (FirstElt < AvailableValues.size()) {  // #Elements may be zero.
-    SILValue FirstVal = AvailableValues[FirstElt].first;
-    if (FirstVal && AvailableValues[FirstElt].second == 0 &&
-        FirstVal->getType() == LoadTy) {
-      // If the first element of this value is available, check any extra ones
-      // before declaring success.
-      bool AllMatch = true;
-      for (unsigned i = 0, e = getNumSubElements(LoadTy, M); i != e; ++i)
-        if (AvailableValues[FirstElt+i].first != FirstVal ||
-            AvailableValues[FirstElt+i].second != i) {
-          AllMatch = false;
-          break;
-        }
-      
-      if (AllMatch)
-        return FirstVal;
-    }
-  }
-  
-  
-  SILBuilderWithScope B(Inst);
-  
-  if (TupleType *TT = LoadTy.getAs<TupleType>()) {
-    SmallVector<SILValue, 4> ResultElts;
-    
-    for (unsigned EltNo : indices(TT->getElements())) {
-      SILType EltTy = LoadTy.getTupleElementType(EltNo);
-      unsigned NumSubElt = getNumSubElements(EltTy, M);
-      
-      // If we are missing any of the available values in this struct element,
-      // compute an address to load from.
-      SILValue EltAddr;
-      if (anyMissing(FirstElt, NumSubElt, AvailableValues))
-        EltAddr = B.createTupleElementAddr(Inst->getLoc(), Address, EltNo,
-                                           EltTy.getAddressType());
+  // FIXME: This is not an aggressive implementation.  :)
 
-      ResultElts.push_back(aggregateAvailableValues(Inst, EltTy, EltAddr,
-                                                    AvailableValues, FirstElt));
-      FirstElt += NumSubElt;
-    }
-    
-    return B.createTuple(Inst->getLoc(), LoadTy, ResultElts);
-  }
-  
-  // Extract struct elements from fully referenceable structs.
-  if (auto *SD = getFullyReferenceableStruct(LoadTy)) {
-    SmallVector<SILValue, 4> ResultElts;
-    
-    for (auto *FD : SD->getStoredProperties()) {
-      SILType EltTy = LoadTy.getFieldType(FD, M);
-      unsigned NumSubElt = getNumSubElements(EltTy, M);
-      
-      // If we are missing any of the available values in this struct element,
-      // compute an address to load from.
-      SILValue EltAddr;
-      if (anyMissing(FirstElt, NumSubElt, AvailableValues))
-        EltAddr = B.createStructElementAddr(Inst->getLoc(), Address, FD,
-                                            EltTy.getAddressType());
-
-      ResultElts.push_back(aggregateAvailableValues(Inst, EltTy, EltAddr,
-                                                    AvailableValues, FirstElt));
-      FirstElt += NumSubElt;
-    }
-    return B.createStruct(Inst->getLoc(), LoadTy, ResultElts);
-  }
-  
-  // Otherwise, we have a simple primitive.  If the value is available, use it,
-  // otherwise emit a load of the value.
-  auto Val = AvailableValues[FirstElt];
-  if (!Val.first)
-    return B.createLoad(Inst->getLoc(), Address,
-                        LoadOwnershipQualifier::Unqualified);
-
-  SILValue EltVal = extractSubElement(Val.first, Val.second, B, Inst->getLoc());
-  // It must be the same type as LoadTy if available.
-  assert(EltVal->getType() == LoadTy &&
-         "Subelement types mismatch");
-  return EltVal;
+  // TODO: At some point, we should special case closures that just *read* from
+  // the escaped value (by looking at the body of the closure).  They should not
+  // prevent load promotion, and will allow promoting values like X in regions
+  // dominated by "... && X != 0".
+  return HasAnyEscape;
 }
 
+//===----------------------------------------------------------------------===//
+//                          Allocation Optimization
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// This performs load promotion and deletes synthesized allocations if all
+/// loads can be removed.
+class AllocOptimize {
+
+  SILModule &Module;
+
+  /// This is either an alloc_box or alloc_stack instruction.
+  AllocationInst *TheMemory;
+
+  /// This is the SILType of the memory object.
+  SILType MemoryType;
+
+  /// The number of primitive subelements across all elements of this memory
+  /// value.
+  unsigned NumMemorySubElements;
+
+  SmallVectorImpl<DIMemoryUse> &Uses;
+  SmallVectorImpl<SILInstruction *> &Releases;
+
+  /// A structure that we use to compute our available values.
+  AvailableValueDataflowContext DataflowContext;
+
+public:
+  AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
+                SmallVectorImpl<SILInstruction *> &Releases);
+
+  bool doIt();
+
+private:
+  bool promoteLoad(SILInstruction *Inst);
+  void promoteDestroyAddr(DestroyAddrInst *DAI,
+                          MutableArrayRef<AvailableValue> Values);
+  bool
+  canPromoteDestroyAddr(DestroyAddrInst *DAI,
+                        llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
+
+  bool tryToRemoveDeadAllocation();
+};
+
+} // end anonymous namespace
+
+static SILType getMemoryType(AllocationInst *TheMemory) {
+  // Compute the type of the memory object.
+  if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
+    assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 &&
+           "optimizing multi-field boxes not implemented");
+    return ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
+  } else {
+    assert(isa<AllocStackInst>(TheMemory));
+    return cast<AllocStackInst>(TheMemory)->getElementType();
+  }
+}
+
+AllocOptimize::AllocOptimize(AllocationInst *InputMemory,
+                             SmallVectorImpl<DIMemoryUse> &InputUses,
+                             SmallVectorImpl<SILInstruction *> &InputReleases)
+    : Module(InputMemory->getModule()), TheMemory(InputMemory),
+      MemoryType(getMemoryType(TheMemory)),
+      NumMemorySubElements(getNumSubElements(MemoryType, Module)),
+      Uses(InputUses), Releases(InputReleases),
+      DataflowContext(TheMemory, NumMemorySubElements, Uses) {}
+
+/// If we are able to optimize \p Inst, return the source address that
+/// instruction is loading from. If we can not optimize \p Inst, then just
+/// return an empty SILValue.
+static SILValue tryFindSrcAddrForLoad(SILInstruction *Inst) {
+  // We only handle load [copy], load [trivial] and copy_addr right now.
+  if (auto *LI = dyn_cast<LoadInst>(Inst))
+    return LI->getOperand();
+
+  // If this is a CopyAddr, verify that the element type is loadable.  If not,
+  // we can't explode to a load.
+  auto *CAI = dyn_cast<CopyAddrInst>(Inst);
+  if (!CAI || !CAI->getSrc()->getType().isLoadable(CAI->getModule()))
+    return SILValue();
+  return CAI->getSrc();
+}
 
 /// At this point, we know that this element satisfies the definitive init
 /// requirements, so we can try to promote loads to enable SSA-based dataflow
@@ -613,40 +1055,31 @@
 /// cross element accesses have been scalarized.
 ///
 /// This returns true if the load has been removed from the program.
-///
 bool AllocOptimize::promoteLoad(SILInstruction *Inst) {
   // Note that we intentionally don't support forwarding of weak pointers,
   // because the underlying value may drop be deallocated at any time.  We would
   // have to prove that something in this function is holding the weak value
   // live across the promoted region and that isn't desired for a stable
   // diagnostics pass this like one.
-  
-  // We only handle load and copy_addr right now.
-  SILValue src;
-  if (auto CAI = dyn_cast<CopyAddrInst>(Inst)) {
-    // If this is a CopyAddr, verify that the element type is loadable.  If not,
-    // we can't explode to a load.
-    src = CAI->getSrc();
-    if (!src->getType().isLoadable(Module))
-      return false;
-  } else if (auto load = dyn_cast<LoadInst>(Inst)) {
-    src = load->getOperand();
-  } else {
+
+  // First attempt to find a source addr for our "load" instruction. If we fail
+  // to find a valid value, just return.
+  SILValue SrcAddr = tryFindSrcAddrForLoad(Inst);
+  if (!SrcAddr)
     return false;
-  }
 
   // If the box has escaped at this instruction, we can't safely promote the
   // load.
-  if (hasEscapedAt(Inst))
+  if (DataflowContext.hasEscapedAt(Inst))
     return false;
-  
-  SILType LoadTy = src->getType().getObjectType();
-  
+
+  SILType LoadTy = SrcAddr->getType().getObjectType();
+
   // If this is a load/copy_addr from a struct field that we want to promote,
   // compute the access path down to the field so we can determine precise
   // def/use behavior.
-  unsigned FirstElt = computeSubelement(src, TheMemory);
-  
+  unsigned FirstElt = computeSubelement(SrcAddr, TheMemory);
+
   // If this is a load from within an enum projection, we can't promote it since
   // we don't track subelements in a type that could be changing.
   if (FirstElt == ~0U)
@@ -657,34 +1090,23 @@
   // Set up the bitvector of elements being demanded by the load.
   llvm::SmallBitVector RequiredElts(NumMemorySubElements);
   RequiredElts.set(FirstElt, FirstElt+NumLoadSubElements);
-  
-  SmallVector<std::pair<SILValue, unsigned>, 8> AvailableValues;
+
+  SmallVector<AvailableValue, 8> AvailableValues;
   AvailableValues.resize(NumMemorySubElements);
   
   // Find out if we have any available values.  If no bits are demanded, we
   // trivially succeed. This can happen when there is a load of an empty struct.
-  if (NumLoadSubElements != 0) {
-    computeAvailableValues(Inst, RequiredElts, AvailableValues);
-    
-    // If there are no values available at this load point, then we fail to
-    // promote this load and there is nothing to do.
-    bool AnyAvailable = false;
-    for (unsigned i = FirstElt, e = i+NumLoadSubElements; i != e; ++i)
-      if (AvailableValues[i].first) {
-        AnyAvailable = true;
-        break;
-      }
-    
-    if (!AnyAvailable)
-      return false;
-  }
-  
+  if (NumLoadSubElements != 0 &&
+      !DataflowContext.computeAvailableValues(
+          Inst, FirstElt, NumLoadSubElements, RequiredElts, AvailableValues))
+    return false;
+
   // Ok, we have some available values.  If we have a copy_addr, explode it now,
   // exposing the load operation within it.  Subsequent optimization passes will
   // see the load and propagate the available values into it.
   if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
-    explodeCopyAddr(CAI);
-    
+    DataflowContext.explodeCopyAddr(CAI);
+
     // This is removing the copy_addr, but explodeCopyAddr takes care of
     // removing the instruction from Uses for us, so we return false.
     return false;
@@ -693,9 +1115,9 @@
   // Aggregate together all of the subelements into something that has the same
   // type as the load did, and emit smaller) loads for any subelements that were
   // not available.
-  auto Load = cast<LoadInst>(Inst);
-  auto NewVal = aggregateAvailableValues(Load, LoadTy, Load->getOperand(),
-                                         AvailableValues, FirstElt);
+  auto *Load = cast<LoadInst>(Inst);
+  AvailableValueAggregator Agg(Load, AvailableValues, Uses);
+  SILValue NewVal = Agg.aggregateValues(LoadTy, Load->getOperand(), FirstElt);
 
   ++NumLoadPromoted;
   
@@ -711,15 +1133,12 @@
   return true;
 }
 
-/// promoteDestroyAddr - DestroyAddr is a composed operation merging
-/// load+strong_release.  If the implicit load's value is available, explode it.
-///
-/// Note that we handle the general case of a destroy_addr of a piece of the
-/// memory object, not just destroy_addrs of the entire thing.
-///
-bool AllocOptimize::promoteDestroyAddr(DestroyAddrInst *DAI) {
+/// Return true if we can promote the given destroy.
+bool AllocOptimize::canPromoteDestroyAddr(
+    DestroyAddrInst *DAI,
+    llvm::SmallVectorImpl<AvailableValue> &AvailableValues) {
   SILValue Address = DAI->getOperand();
-  
+
   // We cannot promote destroys of address-only types, because we can't expose
   // the load.
   SILType LoadTy = Address->getType().getObjectType();
@@ -728,7 +1147,7 @@
   
   // If the box has escaped at this instruction, we can't safely promote the
   // load.
-  if (hasEscapedAt(DAI))
+  if (DataflowContext.hasEscapedAt(DAI))
     return false;
   
   // Compute the access path down to the field so we can determine precise
@@ -740,26 +1159,47 @@
   // Set up the bitvector of elements being demanded by the load.
   llvm::SmallBitVector RequiredElts(NumMemorySubElements);
   RequiredElts.set(FirstElt, FirstElt+NumLoadSubElements);
-  
-  SmallVector<std::pair<SILValue, unsigned>, 8> AvailableValues;
-  AvailableValues.resize(NumMemorySubElements);
-  
+
   // Find out if we have any available values.  If no bits are demanded, we
   // trivially succeed. This can happen when there is a load of an empty struct.
-  if (NumLoadSubElements != 0) {
-    computeAvailableValues(DAI, RequiredElts, AvailableValues);
-    
-    // If some value is not available at this load point, then we fail.
-    for (unsigned i = FirstElt, e = FirstElt+NumLoadSubElements; i != e; ++i)
-      if (!AvailableValues[i].first)
-        return false;
-  }
-  
+  if (NumLoadSubElements == 0)
+    return true;
+
+  // Compute our available values. If we do not have any available values,
+  // return false. We have nothing further to do.
+  llvm::SmallVector<AvailableValue, 8> TmpList;
+  TmpList.resize(NumMemorySubElements);
+  if (!DataflowContext.computeAvailableValues(DAI, FirstElt, NumLoadSubElements,
+                                              RequiredElts, TmpList))
+    return false;
+
+  // Now that we have our final list, move the temporary lists contents into
+  // AvailableValues.
+  std::move(TmpList.begin(), TmpList.end(),
+            std::back_inserter(AvailableValues));
+
+  return true;
+}
+
+/// promoteDestroyAddr - DestroyAddr is a composed operation merging
+/// load+strong_release.  If the implicit load's value is available, explode it.
+///
+/// Note that we handle the general case of a destroy_addr of a piece of the
+/// memory object, not just destroy_addrs of the entire thing.
+void AllocOptimize::promoteDestroyAddr(
+    DestroyAddrInst *DAI, MutableArrayRef<AvailableValue> AvailableValues) {
+  SILValue Address = DAI->getOperand();
+  SILType LoadTy = Address->getType().getObjectType();
+
+  // Compute the access path down to the field so we can determine precise
+  // def/use behavior.
+  unsigned FirstElt = computeSubelement(Address, TheMemory);
+
   // Aggregate together all of the subelements into something that has the same
   // type as the load did, and emit smaller) loads for any subelements that were
   // not available.
-  auto NewVal =
-      aggregateAvailableValues(DAI, LoadTy, Address, AvailableValues, FirstElt);
+  AvailableValueAggregator Agg(DAI, AvailableValues, Uses);
+  SILValue NewVal = Agg.aggregateValues(LoadTy, Address, FirstElt);
 
   ++NumDestroyAddrPromoted;
   
@@ -768,108 +1208,6 @@
 
   SILBuilderWithScope(DAI).emitDestroyValueOperation(DAI->getLoc(), NewVal);
   DAI->eraseFromParent();
-  return true;
-}
-
-
-
-/// Explode a copy_addr instruction of a loadable type into lower level
-/// operations like loads, stores, retains, releases, retain_value, etc.
-void AllocOptimize::explodeCopyAddr(CopyAddrInst *CAI) {
-  DEBUG(llvm::dbgs() << "  -- Exploding copy_addr: " << *CAI << "\n");
-  
-  SILType ValTy = CAI->getDest()->getType().getObjectType();
-  auto &TL = Module.getTypeLowering(ValTy);
-  
-  // Keep track of the new instructions emitted.
-  SmallVector<SILInstruction*, 4> NewInsts;
-  SILBuilder B(CAI, &NewInsts);
-  B.setCurrentDebugScope(CAI->getDebugScope());
-  
-  // Use type lowering to lower the copyaddr into a load sequence + store
-  // sequence appropriate for the type.
-  SILValue StoredValue = TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(),
-                                           CAI->isTakeOfSrc());
-  
-  TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
-                     CAI->isInitializationOfDest());
-
-  // Update our internal state for this being gone.
-  NonLoadUses.erase(CAI);
-  
-  // Remove the copy_addr from Uses.  A single copy_addr can appear multiple
-  // times if the source and dest are to elements within a single aggregate, but
-  // we only want to pick up the CopyAddrKind from the store.
-  DIMemoryUse LoadUse, StoreUse;
-  for (auto &Use : Uses) {
-    if (Use.Inst != CAI) continue;
-    
-    if (Use.Kind == DIUseKind::Load) {
-      assert(LoadUse.isInvalid());
-      LoadUse = Use;
-    } else {
-      assert(StoreUse.isInvalid());
-      StoreUse = Use;
-    }
-    
-    Use.Inst = nullptr;
-    
-    // Keep scanning in case the copy_addr appears multiple times.
-  }
-  
-  assert((LoadUse.isValid() || StoreUse.isValid()) &&
-         "we should have a load or a store, possibly both");
-  assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
-         StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
-  
-  // Now that we've emitted a bunch of instructions, including a load and store
-  // but also including other stuff, update the internal state of
-  // LifetimeChecker to reflect them.
-  
-  // Update the instructions that touch the memory.  NewInst can grow as this
-  // iterates, so we can't use a foreach loop.
-  for (auto *NewInst : NewInsts) {
-    switch (NewInst->getKind()) {
-    default:
-      NewInst->dump();
-      llvm_unreachable("Unknown instruction generated by copy_addr lowering");
-      
-    case SILInstructionKind::StoreInst:
-      // If it is a store to the memory object (as oppose to a store to
-      // something else), track it as an access.
-      if (StoreUse.isValid()) {
-        StoreUse.Inst = NewInst;
-        NonLoadUses[NewInst] = Uses.size();
-        Uses.push_back(StoreUse);
-      }
-      continue;
-      
-    case SILInstructionKind::LoadInst:
-      // If it is a load from the memory object (as oppose to a load from
-      // something else), track it as an access.  We need to explicitly check to
-      // see if the load accesses "TheMemory" because it could either be a load
-      // for the copy_addr source, or it could be a load corresponding to the
-      // "assign" operation on the destination of the copyaddr.
-      if (LoadUse.isValid() &&
-          getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
-        LoadUse.Inst = NewInst;
-        Uses.push_back(LoadUse);
-      }
-      continue;
-      
-    case SILInstructionKind::RetainValueInst:
-    case SILInstructionKind::StrongRetainInst:
-    case SILInstructionKind::StrongReleaseInst:
-    case SILInstructionKind::UnownedRetainInst:
-    case SILInstructionKind::UnownedReleaseInst:
-    case SILInstructionKind::ReleaseValueInst:   // Destroy overwritten value
-      // These are ignored.
-      continue;
-    }
-  }
-
-  // Next, remove the copy_addr itself.
-  CAI->eraseFromParent();
 }
 
 /// tryToRemoveDeadAllocation - If the allocation is an autogenerated allocation
@@ -925,17 +1263,55 @@
 
   // If the memory object has non-trivial type, then removing the deallocation
   // will drop any releases.  Check that there is nothing preventing removal.
+  llvm::SmallVector<unsigned, 8> DestroyAddrIndices;
+  llvm::SmallVector<AvailableValue, 32> AvailableValueList;
+  llvm::SmallVector<unsigned, 8> AvailableValueStartOffsets;
+
   if (!MemoryType.isTrivial(Module)) {
-    for (auto *R : Releases) {
+    for (auto P : llvm::enumerate(Releases)) {
+      auto *R = P.value();
       if (R == nullptr || isa<DeallocStackInst>(R) || isa<DeallocBoxInst>(R))
         continue;
 
+      // We stash all of the destroy_addr that we see.
+      if (auto *DAI = dyn_cast<DestroyAddrInst>(R)) {
+        AvailableValueStartOffsets.push_back(AvailableValueList.size());
+        // Make sure we can actually promote this destroy addr. If we can not,
+        // then we must bail. In order to not gather available values twice, we
+        // gather the available values here that we will use to promote the
+        // values.
+        if (!canPromoteDestroyAddr(DAI, AvailableValueList))
+          return false;
+        DestroyAddrIndices.push_back(P.index());
+        continue;
+      }
+
       DEBUG(llvm::dbgs() << "*** Failed to remove autogenerated alloc: "
             "kept alive by release: " << *R);
       return false;
     }
   }
 
+  // If we reached this point, we can promote all of our destroy_addr.
+  for (auto P : llvm::enumerate(DestroyAddrIndices)) {
+    unsigned DestroyAddrIndex = P.value();
+    unsigned AvailableValueIndex = P.index();
+    unsigned StartOffset = AvailableValueStartOffsets[AvailableValueIndex];
+    unsigned Count;
+
+    if ((AvailableValueStartOffsets.size() - 1) != AvailableValueIndex) {
+      Count = AvailableValueStartOffsets[AvailableValueIndex + 1] - StartOffset;
+    } else {
+      Count = AvailableValueList.size() - StartOffset;
+    }
+
+    MutableArrayRef<AvailableValue> Values(&AvailableValueList[StartOffset],
+                                           Count);
+    auto *DAI = cast<DestroyAddrInst>(Releases[DestroyAddrIndex]);
+    promoteDestroyAddr(DAI, Values);
+    Releases[DestroyAddrIndex] = nullptr;
+  }
+
   DEBUG(llvm::dbgs() << "*** Removing autogenerated alloc_stack: "<<*TheMemory);
 
   // If it is safe to remove, do it.  Recursively remove all instructions
@@ -968,22 +1344,11 @@
     }
   }
   
-  // destroy_addr(p) is strong_release(load(p)), try to promote it too.
-  for (unsigned i = 0; i != Releases.size(); ++i) {
-    if (auto *DAI = dyn_cast_or_null<DestroyAddrInst>(Releases[i]))
-      if (promoteDestroyAddr(DAI)) {
-        // remove entry if destroy_addr got deleted.
-        Releases[i] = nullptr;
-        Changed = true;
-      }
-  }
-
   // If this is an allocation, try to remove it completely.
   Changed |= tryToRemoveDeadAllocation();
 
   return Changed;
- }
-
+}
 
 static bool optimizeMemoryAllocations(SILFunction &Fn) {
   bool Changed = false;
@@ -1022,15 +1387,15 @@
 }
 
 namespace {
-class PredictableMemoryOptimizations : public SILFunctionTransform {
 
+class PredictableMemoryOptimizations : public SILFunctionTransform {
   /// The entry point to the transformation.
   void run() override {
     if (optimizeMemoryAllocations(*getFunction()))
       invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
   }
-
 };
+
 } // end anonymous namespace
 
 
diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp
index 736ca54..9eb5407 100644
--- a/lib/SILOptimizer/PassManager/PassManager.cpp
+++ b/lib/SILOptimizer/PassManager/PassManager.cpp
@@ -236,8 +236,9 @@
 };
 
 
-SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage) :
-  Mod(M), StageName(Stage) {
+SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage,
+                               bool isMandatoryPipeline) :
+  Mod(M), StageName(Stage), isMandatoryPipeline(isMandatoryPipeline) {
   
 #define ANALYSIS(NAME) \
   Analysis.push_back(create##NAME##Analysis(Mod));
@@ -250,14 +251,15 @@
 }
 
 SILPassManager::SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
-                               llvm::StringRef Stage)
-    : SILPassManager(M, Stage) {
+                               llvm::StringRef Stage, bool isMandatoryPipeline)
+    : SILPassManager(M, Stage, isMandatoryPipeline) {
   this->IRMod = IRMod;
 }
 
 bool SILPassManager::continueTransforming() {
-  return Mod->getStage() == SILStage::Raw ||
-         NumPassesRun < SILNumOptPassesToRun;
+  if (isMandatoryPipeline)
+    return true;
+  return NumPassesRun < SILNumOptPassesToRun;
 }
 
 bool SILPassManager::analysesUnlocked() {
@@ -389,7 +391,7 @@
 
     // Only include functions that are definitions, and which have not
     // been intentionally excluded from optimization.
-    if (F.isDefinition() && F.shouldOptimize())
+    if (F.isDefinition() && (isMandatoryPipeline || F.shouldOptimize()))
       FunctionWorklist.push_back(*I);
   }
 
@@ -554,8 +556,8 @@
 
 void SILPassManager::addFunctionToWorklist(SILFunction *F,
                                            SILFunction *DerivedFrom) {
-  assert(F && F->isDefinition() && F->shouldOptimize() &&
-         "Expected optimizable function definition!");
+  assert(F && F->isDefinition() && (isMandatoryPipeline || F->shouldOptimize())
+         && "Expected optimizable function definition!");
 
   constexpr int MaxDeriveLevels = 10;
 
diff --git a/lib/SILOptimizer/PassManager/Passes.cpp b/lib/SILOptimizer/PassManager/Passes.cpp
index 94d74e7..761a044 100644
--- a/lib/SILOptimizer/PassManager/Passes.cpp
+++ b/lib/SILOptimizer/PassManager/Passes.cpp
@@ -51,7 +51,7 @@
 
   auto &Ctx = Module.getASTContext();
 
-  SILPassManager PM(&Module);
+  SILPassManager PM(&Module, "", /*isMandatoryPipeline=*/ true);
   PM.executePassPipelinePlan(
       SILPassPipelinePlan::getDiagnosticPassPipeline(Module.getOptions()));
 
@@ -119,7 +119,9 @@
   if (Module.getOptions().VerifyAll)
     Module.verify();
 
-  SILPassManager PM(&Module, "Onone");
+  // We want to run the Onone passes also for function which have an explicit
+  // Onone attribute.
+  SILPassManager PM(&Module, "Onone", /*isMandatoryPipeline=*/ true);
   PM.executePassPipelinePlan(SILPassPipelinePlan::getOnonePassPipeline());
 
   // Verify the module, if required.
@@ -199,7 +201,7 @@
 // convert it to a module pass to ensure that the SIL input is always at the
 // same stage of lowering.
 void swift::runSILLoweringPasses(SILModule &Module) {
-  SILPassManager PM(&Module, "LoweringPasses");
+  SILPassManager PM(&Module, "LoweringPasses", /*isMandatoryPipeline=*/ true);
   PM.executePassPipelinePlan(SILPassPipelinePlan::getLoweringPassPipeline());
 
   assert(Module.getStage() == SILStage::Lowered);
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 7c17964..3fad2e2 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -328,7 +328,9 @@
     for (auto Arg : ToBeReleasedArgs) {
       Builder.emitDestroyValueOperation(PAI->getLoc(), Arg);
     }
-    Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
+    if (!PAI->hasCalleeGuaranteedContext())
+      Builder.createStrongRelease(AI.getLoc(), PAI,
+                                  Builder.getDefaultAtomicity());
     Builder.setInsertionPoint(TAI->getErrorBB()->begin());
     // Release the non-consumed parameters.
     for (auto Arg : ToBeReleasedArgs) {
@@ -487,13 +489,10 @@
       assert(NewOpType.isAddress() && "Addresses should map to addresses.");
       auto UAC = Builder.createUncheckedAddrCast(AI.getLoc(), Op, NewOpType);
       Args.push_back(UAC);
-    } else if (SILType::canRefCast(OldOpType, NewOpType, AI.getModule())) {
-      auto URC = Builder.createUncheckedRefCast(AI.getLoc(), Op, NewOpType);
+    } else if (OldOpType.getSwiftRValueType() != NewOpType.getSwiftRValueType()) {
+      auto URC = Builder.createUncheckedBitCast(AI.getLoc(), Op, NewOpType);
       Args.push_back(URC);
     } else {
-      assert((!OldOpType.isHeapObjectReferenceType()
-              && !NewOpType.isHeapObjectReferenceType()) &&
-             "ref argument types should map to refs.");
       Args.push_back(Op);
     }
   }
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index b92c698..996215f 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -629,7 +629,8 @@
   // the parameters promoted.
   auto ClonedTy = SILFunctionType::get(
       OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
-      OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+      OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+      ClonedInterfaceArgTys, OrigFTI->getYields(),
       OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
       M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
 
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index 6d0e0df..5e1bca0 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -291,6 +291,8 @@
   switch (Term->getTermKind()) {
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
+  case TermKind::UnwindInst:
+  case TermKind::YieldInst:
 
   case TermKind::UnreachableInst:
   case TermKind::SwitchValueInst:
@@ -381,6 +383,7 @@
   switch (cast<TermInst>(I)->getTermKind()) {
   case TermKind::BranchInst:
   case TermKind::UnreachableInst:
+  case TermKind::UnwindInst:
     return;
 
   case TermKind::ReturnInst:
@@ -396,6 +399,7 @@
 
   case TermKind::TryApplyInst:
   case TermKind::SwitchValueInst:
+  case TermKind::YieldInst:
     for (auto &O : I->getAllOperands())
       markValueLive(O.get());
     return;
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index c3304da..d1333cd 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -577,6 +577,12 @@
     InterfaceResults.push_back(InterfaceResult);
   }
 
+  llvm::SmallVector<SILYieldInfo, 8> InterfaceYields;
+  for (SILYieldInfo InterfaceYield : FTy->getYields()) {
+    // For now, don't touch the yield types.
+    InterfaceYields.push_back(InterfaceYield);
+  }
+
   bool UsesGenerics = false;
   if (HasGenericSignature) {
     // Not all of the generic type parameters are used by the function
@@ -630,9 +636,9 @@
       UsesGenerics ? FTy->getGenericSignature() : nullptr;
 
   return SILFunctionType::get(
-      GenericSig, ExtInfo, FTy->getCalleeConvention(), InterfaceParams,
-      InterfaceResults, InterfaceErrorResult, F->getModule().getASTContext(),
-      witnessMethodConformance);
+      GenericSig, ExtInfo, FTy->getCoroutineKind(), FTy->getCalleeConvention(),
+      InterfaceParams, InterfaceYields, InterfaceResults, InterfaceErrorResult,
+      F->getModule().getASTContext(), witnessMethodConformance);
 }
 
 void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
@@ -1142,8 +1148,7 @@
     auto *F = getFunction();
 
     // Don't run function signature optimizations at -Os.
-    if (F->getModule().getOptions().Optimization ==
-        SILOptions::SILOptMode::OptimizeForSize)
+    if (F->optimizeForSize())
       return;
 
     // Don't optimize callees that should not be optimized.
diff --git a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
index 20b88e9..51aff14 100644
--- a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
+++ b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
@@ -84,6 +84,9 @@
       SILFunction *Callee = Apply.getReferencedFunction();
       assert(Callee && "Expected to have a known callee");
 
+      if (!Callee->shouldOptimize())
+        continue;
+
       // We have a call that can potentially be specialized, so
       // attempt to do so.
       llvm::SmallVector<SILFunction *, 2> NewFunctions;
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index 76741f7..6b2687c 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -290,7 +290,8 @@
       SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                /*pseudogeneric*/ false, /*noescape*/ false);
   auto FunctionType = SILFunctionType::get(
-      nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+      nullptr, ExtInfo, SILCoroutineKind::None,
+      ParameterConvention::Direct_Unowned, Parameters, /*yields*/ {},
       Results, None, M.getASTContext());
   return FunctionType;
 }
@@ -697,6 +698,8 @@
   if (!Enum)
     return BridgedArgument();
 
+  if (SILBasicBlock::iterator(Enum) == Enum->getParent()->begin())
+    return BridgedArgument();
   auto *BridgeCall =
       dyn_cast<ApplyInst>(std::prev(SILBasicBlock::iterator(Enum)));
   if (!BridgeCall || BridgeCall->getNumArguments() != 1 ||
@@ -704,11 +707,16 @@
     return BridgedArgument();
 
   auto BridgedValue = BridgeCall->getArgument(0);
+  auto Next = std::next(SILBasicBlock::iterator(Enum));
+  if (Next == Enum->getParent()->end())
+    return BridgedArgument();
   auto *BridgedValueRelease =
       dyn_cast<ReleaseValueInst>(std::next(SILBasicBlock::iterator(Enum)));
   if (!BridgedValueRelease || BridgedValueRelease->getOperand() != BridgedValue)
     return BridgedArgument();
 
+  if (SILBasicBlock::iterator(BridgeCall) == BridgeCall->getParent()->begin())
+    return BridgedArgument();
   auto *FunRef =
       dyn_cast<FunctionRefInst>(std::prev(SILBasicBlock::iterator(BridgeCall)));
   if (!FunRef || !FunRef->hasOneUse() || BridgeCall->getCallee() != FunRef)
@@ -1197,7 +1205,8 @@
         SILResultInfo(BridgedReturn.getReturnType(), ResultConvention::Owned));
   }
   auto FunctionType = SILFunctionType::get(
-      nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+      nullptr, ExtInfo, SILCoroutineKind::None,
+      ParameterConvention::Direct_Unowned, Parameters, {},
       Results, None, M.getASTContext());
   return FunctionType;
 }
@@ -1280,8 +1289,7 @@
     auto *Fun = getFunction();
 
     // Only outline if we optimize for size.
-    if (Fun->getModule().getOptions().Optimization !=
-        SILOptions::SILOptMode::OptimizeForSize)
+    if (!Fun->optimizeForSize())
       return;
 
     // Dump function if requested.
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index 8190a3e..e7273a9 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -111,7 +111,7 @@
     DefaultApplyLength = 10
   };
 
-  SILOptions::SILOptMode OptMode;
+  OptimizationMode OptMode;
 
 #ifndef NDEBUG
   SILFunction *LastPrintedCaller = nullptr;
@@ -161,7 +161,7 @@
 public:
   SILPerformanceInliner(InlineSelection WhatToInline, DominanceAnalysis *DA,
                         SILLoopAnalysis *LA, SideEffectAnalysis *SEA,
-                        SILOptions::SILOptMode OptMode, OptRemark::Emitter &ORE)
+                        OptimizationMode OptMode, OptRemark::Emitter &ORE)
       : WhatToInline(WhatToInline), DA(DA), LA(LA), SEA(SEA), CBI(DA), ORE(ORE),
         OptMode(OptMode) {}
 
@@ -243,7 +243,7 @@
   int BaseBenefit = RemovedCallBenefit;
 
   // Osize heuristic.
-  if (OptMode == SILOptions::SILOptMode::OptimizeForSize) {
+  if (OptMode == OptimizationMode::ForSize) {
     // Don't inline into thunks.
     if (AI.getFunction()->isThunk())
       return false;
@@ -293,11 +293,6 @@
       ->getSubstitutionMap(AI.getSubstitutions());
   }
 
-  // For some reason -Ounchecked can accept a higher base benefit without
-  // increasing the code size too much.
-  if (OptMode == SILOptions::SILOptMode::OptimizeUnchecked)
-    BaseBenefit *= 2;
-
   CallerWeight.updateBenefit(Benefit, BaseBenefit);
   //  Benefit = 1;
 
@@ -443,7 +438,8 @@
     ORE.emit([&]() {
       using namespace OptRemark;
       return RemarkMissed("NoInlinedCost", *AI.getInstruction())
-             << "Not profitable to inline (cost = " << NV("Cost", CalleeCost)
+             << "Not profitable to inline function " << NV("Callee", Callee)
+             << " (cost = " << NV("Cost", CalleeCost)
              << ", benefit = " << NV("Benefit", Benefit) << ")";
     });
     return false;
@@ -905,7 +901,7 @@
       return;
     }
 
-    auto OptMode = getFunction()->getModule().getOptions().Optimization;
+    auto OptMode = getFunction()->getEffectiveOptimizationMode();
 
     SILPerformanceInliner Inliner(WhatToInline, DA, LA, SEA, OptMode, ORE);
 
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index fe6da5e..145a57b 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -2302,6 +2302,8 @@
     case TermKind::ThrowInst:
     case TermKind::DynamicMethodBranchInst:
     case TermKind::ReturnInst:
+    case TermKind::UnwindInst:
+    case TermKind::YieldInst:
       break;
     }
     // If the block has a cond_fail, try to move it to the predecessors.
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index c566949..254c6b7 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -555,8 +555,11 @@
 
       auto &CurFn = *getFunction();
       // Don't perform speculative devirtualization at -Os.
-      if (CurFn.getModule().getOptions().Optimization ==
-          SILOptions::SILOptMode::OptimizeForSize)
+      if (CurFn.optimizeForSize())
+        return;
+
+      // Don't speculatively devirtualize calls inside thunks.
+      if (CurFn.isThunk())
         return;
 
       ClassHierarchyAnalysis *CHA = PM->getAnalysis<ClassHierarchyAnalysis>();
diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
index 3d6da3c..4219ac2 100644
--- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
+++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
@@ -84,7 +84,8 @@
         nullptr, SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
                                           false /*isPseudoGeneric*/,
                                           false /*noescape*/),
-        ParameterConvention::Direct_Unowned, ArrayRef<SILParameterInfo>(),
+        SILCoroutineKind::None, ParameterConvention::Direct_Unowned,
+        ArrayRef<SILParameterInfo>(), ArrayRef<SILYieldInfo>(),
         ResultInfoArray, None, getFunction()->getModule().getASTContext());
 
     SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 452e58d..261512d 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -307,9 +307,25 @@
     return;
   }
 
+  case TermKind::YieldInst: {
+    auto *YI = cast<YieldInst>(T);
+    assert((EdgeIdx == 0 || EdgeIdx == 1) && "Invalid edge index");
+    auto *resumeBB = !EdgeIdx ? NewDest : YI->getResumeBB();
+    auto *unwindBB = EdgeIdx ? NewDest : YI->getUnwindBB();
+    SmallVector<SILValue, 4> yieldedValues;
+    for (auto value : YI->getYieldedValues())
+      yieldedValues.push_back(value);
+
+    B.createYield(YI->getLoc(), yieldedValues, resumeBB, unwindBB);
+
+    YI->eraseFromParent();
+    return;
+  }
+
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
   case TermKind::UnreachableInst:
+  case TermKind::UnwindInst:
     llvm_unreachable("Branch target cannot be changed for this terminator instruction!");
   }
   llvm_unreachable("Not yet implemented!");
@@ -469,6 +485,8 @@
   case TermKind::ThrowInst:
   case TermKind::TryApplyInst:
   case TermKind::UnreachableInst:
+  case TermKind::UnwindInst:
+  case TermKind::YieldInst:
     llvm_unreachable("Branch target cannot be replaced for this terminator instruction!");
   }
   llvm_unreachable("Not yet implemented!");
@@ -830,3 +848,118 @@
   }
   llvm_unreachable("Destination block not found");
 }
+
+void swift::completeJointPostDominanceSet(
+    ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+    llvm::SmallVectorImpl<SILBasicBlock *> &Result) {
+  assert(!UserBlocks.empty() && "Must have at least 1 user block");
+  assert(!DefBlocks.empty() && "Must have at least 1 def block");
+
+  // If we have only one def block and one user block and they are the same
+  // block, then just return.
+  if (DefBlocks.size() == 1 && UserBlocks.size() == 1 &&
+      UserBlocks[0] == DefBlocks[0]) {
+    return;
+  }
+
+  // Some notes on the algorithm:
+  //
+  // 1. Our VisitedBlocks set just states that a value has been added to the
+  // worklist and should not be added to the worklist.
+  // 2. Our targets of the CFG block are DefBlockSet.
+  // 3. We find the missing post-domination blocks by finding successors of
+  // blocks on our walk that we have not visited by the end of the walk. For
+  // joint post-dominance to be true, no such successors should exist.
+
+  // Our set of target blocks where we stop walking.
+  llvm::SmallPtrSet<SILBasicBlock *, 8> DefBlockSet(DefBlocks.begin(),
+                                                    DefBlocks.end());
+
+  // The set of successor blocks of blocks that we visit. Any blocks still in
+  // this set at the end of the walk act as a post-dominating closure around our
+  // UserBlock set.
+  llvm::SmallSetVector<SILBasicBlock *, 16> MustVisitSuccessorBlocks;
+
+  // Add our user and def blocks to the VisitedBlock set. We never want to find
+  // these in our worklist.
+  llvm::SmallPtrSet<SILBasicBlock *, 32> VisitedBlocks(UserBlocks.begin(),
+                                                       UserBlocks.end());
+
+  // Finally setup our worklist by adding our user block predecessors. We only
+  // add the predecessors to the worklist once.
+  llvm::SmallVector<SILBasicBlock *, 32> Worklist;
+  for (auto *Block : UserBlocks) {
+    copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+            [&](SILBasicBlock *PredBlock) -> bool {
+              return VisitedBlocks.insert(PredBlock).second;
+            });
+  }
+
+  // Then until we reach a fix point.
+  while (!Worklist.empty()) {
+    // Grab the next block from the worklist.
+    auto *Block = Worklist.pop_back_val();
+    assert(VisitedBlocks.count(Block) && "All blocks from worklist should be "
+                                         "in the visited blocks set.");
+
+    // Since we are visiting this block now, we know that this block can not be
+    // apart of a the post-dominance closure of our UseBlocks.
+    MustVisitSuccessorBlocks.remove(Block);
+
+    // Then add each successor block of Block that has not been visited yet to
+    // the MustVisitSuccessorBlocks set.
+    for (auto *SuccBlock : Block->getSuccessorBlocks()) {
+      if (!VisitedBlocks.count(SuccBlock)) {
+        MustVisitSuccessorBlocks.insert(SuccBlock);
+      }
+    }
+
+    // If this is a def block, then do not add its predecessors to the
+    // worklist.
+    if (DefBlockSet.count(Block))
+      continue;
+
+    // Otherwise add all unvisited predecessors to the worklist.
+    copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+            [&](SILBasicBlock *Block) -> bool {
+              return VisitedBlocks.insert(Block).second;
+            });
+  }
+
+  // Now that we are done, add all remaining must visit blocks to our result
+  // list. These are the remaining parts of our joint post-dominance closure.
+  copy(MustVisitSuccessorBlocks, std::back_inserter(Result));
+}
+
+bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn,
+                                                          DominanceInfo *DT,
+                                                          SILLoopInfo *LI) {
+  // Find our targets.
+  llvm::SmallVector<std::pair<SILBasicBlock *, unsigned>, 8> Targets;
+  for (auto &Block : Fn) {
+    auto *CBI = dyn_cast<CondBranchInst>(Block.getTerminator());
+    if (!CBI)
+      continue;
+
+    // See if our true index is a critical edge. If so, add block to the list
+    // and continue. If the false edge is also critical, we will handle it at
+    // the same time.
+    if (isCriticalEdge(CBI, CondBranchInst::TrueIdx)) {
+      Targets.emplace_back(&Block, CondBranchInst::TrueIdx);
+    }
+
+    if (!isCriticalEdge(CBI, CondBranchInst::FalseIdx)) {
+      continue;
+    }
+
+    Targets.emplace_back(&Block, CondBranchInst::FalseIdx);
+  }
+
+  for (auto P : Targets) {
+    SILBasicBlock *Block = P.first;
+    unsigned Index = P.second;
+    auto *Result = splitCriticalEdge(Block->getTerminator(), Index, DT, LI);
+    (void)Result;
+    assert(Result);
+  }
+}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 329f349..a24e246 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -528,7 +528,10 @@
     return false;
   }
 
-  if (!F->shouldOptimize()) {
+  // Mandatory inlining does class method devirtualization. I'm not sure if this
+  // is really needed, but some test rely on this.
+  // So even for Onone functions we have to do it if the SILStage is raw.
+  if (F->getModule().getStage() != SILStage::Raw && !F->shouldOptimize()) {
     // Do not consider functions that should not be optimized.
     DEBUG(llvm::dbgs() << "        FAIL: Could not optimize function "
                        << " because it is marked no-opt: " << F->getName()
@@ -712,48 +715,6 @@
 //                        Witness Method Optimization
 //===----------------------------------------------------------------------===//
 
-static SubstitutionMap
-getSubstitutionsForProtocolConformance(ModuleDecl *M,
-                                       ProtocolConformanceRef CRef) {
-  auto C = CRef.getConcrete();
-
-  // Walk down to the base NormalProtocolConformance.
-  SubstitutionList Subs;
-  const ProtocolConformance *ParentC = C;
-  while (!isa<NormalProtocolConformance>(ParentC)) {
-    switch (ParentC->getKind()) {
-    case ProtocolConformanceKind::Normal:
-      llvm_unreachable("should have exited the loop?!");
-    case ProtocolConformanceKind::Inherited:
-      ParentC = cast<InheritedProtocolConformance>(ParentC)
-        ->getInheritedConformance();
-      break;
-    case ProtocolConformanceKind::Specialized: {
-      auto SC = cast<SpecializedProtocolConformance>(ParentC);
-      ParentC = SC->getGenericConformance();
-      assert(Subs.empty() && "multiple conformance specializations?!");
-      Subs = SC->getGenericSubstitutions();
-      break;
-    }
-    }
-  }
-  const NormalProtocolConformance *NormalC
-    = cast<NormalProtocolConformance>(ParentC);
-
-  // If the normal conformance is for a generic type, and we didn't hit a
-  // specialized conformance, collect the substitutions from the generic type.
-  // FIXME: The AST should do this for us.
-  if (!NormalC->getType()->isSpecialized())
-    return SubstitutionMap();
-
-  if (Subs.empty()) {
-    auto *DC = NormalC->getDeclContext();
-    return NormalC->getType()->getContextSubstitutionMap(M, DC);
-  }
-
-  return NormalC->getGenericSignature()->getSubstitutionMap(Subs);
-}
-
 /// Compute substitutions for making a direct call to a SIL function with
 /// @convention(witness_method) convention.
 ///
@@ -823,7 +784,7 @@
 
   // If `Self` maps to a bound generic type, this gives us the
   // substitutions for the concrete type's generic parameters.
-  auto baseSubMap = getSubstitutionsForProtocolConformance(mod, conformanceRef);
+  auto baseSubMap = conformance->getSubstitutions(mod);
 
   unsigned baseDepth = 0;
   auto *rootConformance = conformance->getRootNormalConformance();
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index e7dfb6f..5c49d9f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -347,12 +347,6 @@
 
 static bool shouldNotSpecializeCallee(SILFunction *Callee,
                                       SubstitutionList Subs = {}) {
-  if (!Callee->shouldOptimize()) {
-    DEBUG(llvm::dbgs() << "    Cannot specialize function " << Callee->getName()
-          << " marked to be excluded from optimizations.\n");
-    return true;
-  }
-
   if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
     return true;
 
@@ -721,8 +715,10 @@
 
   // Use the new specialized generic signature.
   auto NewFnTy = SILFunctionType::get(
-      CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
-      FnTy->getParameters(), FnTy->getResults(), FnTy->getOptionalErrorResult(),
+      CanSpecializedGenericSig, FnTy->getExtInfo(),
+      FnTy->getCoroutineKind(), FnTy->getCalleeConvention(),
+      FnTy->getParameters(), FnTy->getYields(),
+      FnTy->getResults(), FnTy->getOptionalErrorResult(),
       M.getASTContext(), FnTy->getWitnessMethodConformanceOrNone());
 
   // This is an interface type. It should not have any archetypes.
@@ -735,6 +731,7 @@
 CanSILFunctionType ReabstractionInfo::
 createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
   llvm::SmallVector<SILResultInfo, 8> SpecializedResults;
+  llvm::SmallVector<SILYieldInfo, 8> SpecializedYields;
   llvm::SmallVector<SILParameterInfo, 8> SpecializedParams;
 
   unsigned IndirectResultIdx = 0;
@@ -769,9 +766,15 @@
       SpecializedParams.push_back(PI);
     }
   }
+  for (SILYieldInfo YI : SubstFTy->getYields()) {
+    // For now, always just use the original, substituted parameter info.
+    SpecializedYields.push_back(YI);
+  }
   return SILFunctionType::get(
-      SubstFTy->getGenericSignature(), SubstFTy->getExtInfo(),
-      SubstFTy->getCalleeConvention(), SpecializedParams, SpecializedResults,
+      SubstFTy->getGenericSignature(),
+      SubstFTy->getExtInfo(), SubstFTy->getCoroutineKind(),
+      SubstFTy->getCalleeConvention(),
+      SpecializedParams, SpecializedYields, SpecializedResults,
       SubstFTy->getOptionalErrorResult(), M.getASTContext(),
       SubstFTy->getWitnessMethodConformanceOrNone());
 }
@@ -1832,12 +1835,10 @@
 /// Create a new specialized function if possible, and cache it.
 SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
   // Do not create any new specializations at Onone.
-  if (M.getOptions().Optimization <= SILOptions::SILOptMode::None)
+  if (!GenericFunc->shouldOptimize())
     return nullptr;
 
-  DEBUG(
-    if (M.getOptions().Optimization <= SILOptions::SILOptMode::Debug) {
-      llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n"; });
+  DEBUG(llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n";);
 
   ReInfo.verify();
 
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 72791f8..62d2bf6 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -89,7 +89,8 @@
   // At Onone, consider all uses, including the debug_info.
   // This way, debug_info is preserved at Onone.
   if (I->hasUsesOfAnyResult() &&
-      I->getModule().getOptions().Optimization <= SILOptions::SILOptMode::None)
+      I->getFunction()->getEffectiveOptimizationMode() <=
+        OptimizationMode::NoOptimization)
     return false;
 
   if (!onlyHaveDebugUsesOfAllResults(I) || isa<TermInst>(I))
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index 96c67bb..107b065 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -338,8 +338,11 @@
   case SILInstructionKind::UnreachableInst:
   case SILInstructionKind::ReturnInst:
   case SILInstructionKind::ThrowInst:
+  case SILInstructionKind::UnwindInst:
+  case SILInstructionKind::YieldInst:
     return InlineCost::Free;
 
+  case SILInstructionKind::AbortApplyInst:
   case SILInstructionKind::ApplyInst:
   case SILInstructionKind::TryApplyInst:
   case SILInstructionKind::AllocBoxInst:
@@ -349,6 +352,7 @@
   case SILInstructionKind::AllocStackInst:
   case SILInstructionKind::AllocValueBufferInst:
   case SILInstructionKind::BindMemoryInst:
+  case SILInstructionKind::BeginApplyInst:
   case SILInstructionKind::ValueMetatypeInst:
   case SILInstructionKind::WitnessMethodInst:
   case SILInstructionKind::AssignInst:
@@ -376,6 +380,7 @@
   case SILInstructionKind::DeinitExistentialAddrInst:
   case SILInstructionKind::DeinitExistentialValueInst:
   case SILInstructionKind::DestroyAddrInst:
+  case SILInstructionKind::EndApplyInst:
   case SILInstructionKind::ProjectValueBufferInst:
   case SILInstructionKind::ProjectBoxInst:
   case SILInstructionKind::ProjectExistentialBoxInst:
diff --git a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
index 75fe849..994d128 100644
--- a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
+++ b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
@@ -78,16 +78,29 @@
 
 /// Are all available values identicalTo each other.
 bool areIdentical(AvailableValsTy &Avails) {
-  // TODO: MultiValueInstruction
-  auto *First = dyn_cast<SingleValueInstruction>(Avails.begin()->second);
-  if (!First)
+  if (auto *First = dyn_cast<SingleValueInstruction>(Avails.begin()->second)) {
+    for (auto Avail : Avails) {
+      auto *Inst = dyn_cast<SingleValueInstruction>(Avail.second);
+      if (!Inst)
+        return false;
+      if (!Inst->isIdenticalTo(First))
+        return false;
+    }
+    return true;
+  }
+
+  auto *MVIR = dyn_cast<MultipleValueInstructionResult>(Avails.begin()->second);
+  if (!MVIR)
     return false;
+
   for (auto Avail : Avails) {
-    auto *Inst = dyn_cast<SingleValueInstruction>(Avail.second);
-    if (!Inst)
+    auto *Result = dyn_cast<MultipleValueInstructionResult>(Avail.second);
+    if (!Result)
       return false;
-    if (!Inst->isIdenticalTo(First))
+    if (!Result->getParent()->isIdenticalTo(MVIR->getParent()) ||
+        Result->getIndex() != MVIR->getIndex()) {
       return false;
+    }
   }
   return true;
 }
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index ca96300..8382876 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -474,9 +474,6 @@
               tc.conformsToProtocol(baseTy, proto, cs.DC,
                                     (ConformanceCheckFlags::InExpression|
                                          ConformanceCheckFlags::Used));
-            assert((!conformance ||
-                    conformance->getConditionalRequirements().empty()) &&
-                   "unhandled conditional conformance");
             if (conformance && conformance->isConcrete()) {
               if (auto witness =
                         conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
@@ -1318,23 +1315,29 @@
       
       // Apply a key path if we have one.
       if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
+        auto applicationTy = simplifyType(selected->openedType)
+          ->castTo<FunctionType>();
+                
         index = cs.coerceToRValue(index);
         // The index argument should be (keyPath: KeyPath<Root, Value>).
         // Dig the key path expression out of the argument tuple.
         auto indexKP = cast<TupleExpr>(index)->getElement(0);
-        auto keyPathTTy = cs.getType(indexKP);
-
+        auto keyPathExprTy = cs.getType(indexKP);
+        auto keyPathTy = applicationTy->getInput()->castTo<TupleType>()
+          ->getElementType(0);
+        
         // Check for the KeyPath being an IUO
-        if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathTTy)) {
-          keyPathTTy = pathTy;
-          indexKP = coerceImplicitlyUnwrappedOptionalToValue(indexKP, keyPathTTy, locator);
+        if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathExprTy)) {
+          keyPathExprTy = pathTy;
+          indexKP = coerceImplicitlyUnwrappedOptionalToValue(
+            indexKP, keyPathExprTy, locator);
         }
 
         Type valueTy;
         Type baseTy;
         bool resultIsLValue;
         
-        if (auto nom = keyPathTTy->getAs<NominalType>()) {
+        if (auto nom = keyPathTy->getAs<NominalType>()) {
           // AnyKeyPath is <T> rvalue T -> rvalue Any?
           if (nom->getDecl() == cs.getASTContext().getAnyKeyPathDecl()) {
             valueTy = ProtocolCompositionType::get(cs.getASTContext(), {},
@@ -1343,12 +1346,25 @@
             resultIsLValue = false;
             base = cs.coerceToRValue(base);
             baseTy = cs.getType(base);
+            // We don't really want to attempt AnyKeyPath application
+            // if we know a more specific key path type is being applied.
+            if (!keyPathTy->isEqual(keyPathExprTy)) {
+              cs.TC.diagnose(base->getLoc(),
+                             diag::expr_smart_keypath_application_type_mismatch,
+                             keyPathExprTy,
+                             baseTy)
+                .highlight(index->getSourceRange());
+            }
           } else {
             llvm_unreachable("unknown key path class!");
           }
         } else {
-          auto keyPathBGT = keyPathTTy->castTo<BoundGenericType>();
+          auto keyPathBGT = keyPathTy->castTo<BoundGenericType>();
           baseTy = keyPathBGT->getGenericArgs()[0];
+          
+          // Coerce the base to the key path's expected base type.
+          if (!baseTy->isEqual(cs.getType(base)->getRValueType()))
+            base = coerceToType(base, baseTy, locator);
 
           if (keyPathBGT->getDecl()
                 == cs.getASTContext().getPartialKeyPathDecl()) {
@@ -1377,12 +1393,6 @@
               llvm_unreachable("unknown key path class!");
             }
           }
-
-          // Coerce the base if its anticipated type doesn't match - say we're
-          // applying a keypath with an existential base to a concrete base.
-          if (baseTy->isExistentialType() && !cs.getType(base)->isExistentialType()) {
-            base = coerceToType(base, baseTy, locator);
-          }
         }
         if (resultIsLValue)
           valueTy = LValueType::get(valueTy);
@@ -7527,6 +7537,16 @@
                                                         DC);
     if (!useAs && !useAsBang)
       return false;
+    
+    // If we're performing pattern matching, "as" means something completely different...
+    if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
+      auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
+      if (overloadedFn && overloadedFn->getDecls().size() > 0) {
+        ValueDecl *decl0 = overloadedFn->getDecls()[0];
+        if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
+          return false;
+      }
+    }
 
     bool needsParensInside = exprNeedsParensBeforeAddingAs(TC, DC, affected);
     bool needsParensOutside = exprNeedsParensAfterAddingAs(TC, DC, affected,
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bf8f627..90f5bb9 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4844,7 +4844,7 @@
     AFD = dyn_cast<AbstractFunctionDecl>(candidate);
   }
 
-  if (!AFD || !AFD->isGeneric() || !AFD->hasInterfaceType())
+  if (!AFD || !AFD->getGenericSignature() || !AFD->hasInterfaceType())
     return false;
 
   auto env = AFD->getGenericEnvironment();
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index fecfb81..e14dae2 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -563,15 +563,6 @@
         break;
       }
 
-      if (conformance) {
-        assert(relationshipKind == SelfTypeRelationship::ConformsTo ||
-               relationshipKind == SelfTypeRelationship::ConformedToBy);
-
-        for (auto requirement : conformance->getConditionalRequirements()) {
-          cs.addConstraint(requirement, locator);
-        }
-      }
-
       bool fewerEffectiveParameters = false;
       switch (checkKind) {
       case CheckAll:
@@ -1045,16 +1036,6 @@
       continue;
     }
 
-    // A concrete type is better than an archetype.
-    // FIXME: Total hack.
-    if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) {
-      if (type1->is<ArchetypeType>())
-        ++score2;
-      else
-        ++score1;
-      continue;
-    }
-    
     // FIXME:
     // This terrible hack is in place to support equality comparisons of non-
     // equatable option types to 'nil'. Until we have a way to constrain a type
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 4e2d031..e5a406a 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -18,6 +18,7 @@
 #include "ConstraintSystem.h"
 #include "swift/AST/ExistentialLayout.h"
 #include "swift/AST/ParameterList.h"
+#include "swift/AST/ProtocolConformance.h"
 #include "swift/Basic/StringExtras.h"
 #include "swift/ClangImporter/ClangModule.h"
 #include "llvm/Support/Compiler.h"
@@ -2606,11 +2607,19 @@
       // This conformance may be conditional, in which case we need to consider
       // those requirements as constraints too.
       //
-      // FIXME: this doesn't seem to be right; the requirements are sometimes
-      // phrased in terms of the type's generic parameters, not type variables
-      // in this context.
-      for (auto req : conformance->getConditionalRequirements()) {
-        addConstraint(req, locator);
+      // If we've got a normal conformance, we must've started with `type` in
+      // the context that declares the conformance, and so these requirements
+      // are automatically satisfied, and thus we can skip adding them. (This
+      // hacks around some representational problems caused by requirements
+      // being stored as interface types and the normal conformance's type being
+      // a contextual type. Once the latter is fixed and everything is interface
+      // types, this shouldn't be necessary.)
+      if (conformance->isConcrete() &&
+          conformance->getConcrete()->getKind() !=
+              ProtocolConformanceKind::Normal) {
+        for (auto req : conformance->getConditionalRequirements()) {
+          addConstraint(req, locator);
+        }
       }
       return SolutionKind::Solved;
     }
@@ -4034,22 +4043,28 @@
     
     // Try to match the root type.
     rootTy = getFixedTypeRecursive(rootTy, flags, /*wantRValue=*/false);
-    auto rootMatches = matchTypes(kpRootTy, rootTy,
-                                  ConstraintKind::Equal,
-                                  subflags, locator);
-    switch (rootMatches) {
-    case SolutionKind::Error:
-      return SolutionKind::Error;
-    case SolutionKind::Solved:
-      break;
-    case SolutionKind::Unsolved:
-      llvm_unreachable("should have generated constraints");
-    }
+
+    auto matchRoot = [&](ConstraintKind kind) -> bool {
+      auto rootMatches = matchTypes(rootTy, kpRootTy, kind,
+                                    subflags, locator);
+      switch (rootMatches) {
+      case SolutionKind::Error:
+        return false;
+      case SolutionKind::Solved:
+        return true;
+      case SolutionKind::Unsolved:
+        llvm_unreachable("should have generated constraints");
+      }
+    };
 
     if (bgt->getDecl() == getASTContext().getPartialKeyPathDecl()) {
       // Read-only keypath, whose projected value is upcast to `Any`.
       auto resultTy = ProtocolCompositionType::get(getASTContext(), {},
                                                   /*explicit AnyObject*/ false);
+
+      if (!matchRoot(ConstraintKind::Conversion))
+        return SolutionKind::Error;
+
       return matchTypes(resultTy, valueTy,
                         ConstraintKind::Bind, subflags, locator);
     }
@@ -4060,6 +4075,7 @@
 
     /// Solve for an rvalue base.
     auto solveRValue = [&]() -> ConstraintSystem::SolutionKind {
+      // An rvalue base can be converted to a supertype.
       return matchTypes(kpValueTy, valueTy,
                         ConstraintKind::Bind, subflags, locator);
     };
@@ -4076,14 +4092,20 @@
       return matchTypes(LValueType::get(kpValueTy), valueTy,
                         ConstraintKind::Bind, subflags, locator);
     };
-
   
     if (bgt->getDecl() == getASTContext().getKeyPathDecl()) {
       // Read-only keypath.
+      if (!matchRoot(ConstraintKind::Conversion))
+        return SolutionKind::Error;
+
       return solveRValue();
     }
     if (bgt->getDecl() == getASTContext().getWritableKeyPathDecl()) {
       // Writable keypath. The result can be an lvalue if the root was.
+      // We can't convert the base without giving up lvalue-ness, though.
+      if (!matchRoot(ConstraintKind::Equal))
+        return SolutionKind::Error;
+
       if (rootTy->is<LValueType>())
         return solveLValue();
       if (rootTy->isTypeVariableOrMember())
@@ -4092,6 +4114,9 @@
       return solveRValue();
     }
     if (bgt->getDecl() == getASTContext().getReferenceWritableKeyPathDecl()) {
+      if (!matchRoot(ConstraintKind::Conversion))
+        return SolutionKind::Error;
+
       // Reference-writable keypath. The result can always be an lvalue.
       return solveLValue();
     }
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 38d6a0d..882d537 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2205,9 +2205,3 @@
 
   return ctor;
 }
-
-void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
-  auto *DD = CD->addImplicitDestructor();
-  if (DD)
-    typeCheckDecl(DD, /*isFirstPass=*/true);
-}
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 39c5ae6..8fbfe3d 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -390,14 +390,12 @@
                                               ConstraintLocatorBuilder locator,
                                               OpenedTypeMap &replacements) {
   auto unboundDecl = unbound->getDecl();
-  if (unboundDecl->isInvalid())
-    return ErrorType::get(getASTContext());
 
   // If the unbound decl hasn't been validated yet, we have a circular
   // dependency that isn't being diagnosed properly.
   if (!unboundDecl->getGenericSignature()) {
     TC.diagnose(unboundDecl, diag::circular_reference);
-    return ErrorType::get(unbound);
+    return Type();
   }
 
   auto parentTy = unbound->getParent();
@@ -458,7 +456,7 @@
   if (!type->hasUnboundGenericType())
     return type;
 
-  return type.transform([&](Type type) -> Type {
+  type = type.transform([&](Type type) -> Type {
       if (auto unbound = type->getAs<UnboundGenericType>()) {
         OpenedTypeMap replacements;
         return openUnboundGenericType(unbound, locator, replacements);
@@ -466,6 +464,11 @@
 
       return type;
     });
+
+  if (!type)
+    return ErrorType::get(getASTContext());
+
+  return type;
 }
 
 Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements) {
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 72124cc..fa3707a 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -671,7 +671,7 @@
                                     FunctionType::ExtInfo());
   }
   eqDecl->setInterfaceType(interfaceTy);
-  copyFormalAccess(eqDecl, typeDecl);
+  eqDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -1090,7 +1090,7 @@
                                       AnyFunctionType::ExtInfo());
 
   getterDecl->setInterfaceType(interfaceType);
-  copyFormalAccess(getterDecl, typeDecl);
+  getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -1106,7 +1106,7 @@
   hashValueDecl->setInterfaceType(intType);
   hashValueDecl->makeComputed(SourceLoc(), getterDecl,
                               nullptr, nullptr, SourceLoc());
-  copyFormalAccess(hashValueDecl, typeDecl);
+  hashValueDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
   hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index c3fb22a..853e9ed 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -349,7 +349,7 @@
   }
   initDecl->setInterfaceType(allocIfaceType);
   initDecl->setInitializerInterfaceType(initIfaceType);
-  copyFormalAccess(initDecl, enumDecl);
+  initDecl->copyFormalAccessAndVersionedAttrFrom(enumDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 0beaf5f..f2e6d36 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -251,7 +251,7 @@
     interfaceType = FunctionType::get({selfParam}, interfaceType,
                                       FunctionType::ExtInfo());
   getterDecl->setInterfaceType(interfaceType);
-  copyFormalAccess(getterDecl, typeDecl);
+  getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
 
   // If the enum was not imported, the derived conformance is either from the
   // enum itself or an extension, in which case we will emit the declaration
@@ -281,7 +281,7 @@
   propDecl->setImplicit();
   propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
                          SourceLoc());
-  copyFormalAccess(propDecl, typeDecl);
+  propDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
   propDecl->setInterfaceType(propertyInterfaceType);
 
   // If this is supposed to be a final property, mark it as such.
@@ -304,14 +304,3 @@
 
   return {propDecl, pbDecl};
 }
-
-void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
-  dest->setAccess(source->getFormalAccess());
-
-  // Inherit the @_versioned attribute.
-  if (source->getAttrs().hasAttribute<VersionedAttr>()) {
-    auto &ctx = source->getASTContext();
-    auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
-    dest->getAttrs().add(clonedAttr);
-  }
-}
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 0e6ab8b..2457971 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -185,9 +185,6 @@
 /// Build a reference to the 'self' decl of a derived function.
 DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
 
-/// Copy access from the source decl to the destination decl.
-void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
-
 }
   
 }
diff --git a/lib/Sema/InstrumenterSupport.h b/lib/Sema/InstrumenterSupport.h
index dd4e71c..f223617 100644
--- a/lib/Sema/InstrumenterSupport.h
+++ b/lib/Sema/InstrumenterSupport.h
@@ -17,6 +17,8 @@
 
 #include "TypeChecker.h"
 
+#include "swift/AST/ASTWalker.h"
+
 namespace swift {
 namespace instrumenter_support {
 
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 0dbc520..27f2bff 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -1418,7 +1418,15 @@
     ///       x == nil    // also !=
     ///
     void checkOptionalPromotions(ApplyExpr *call) {
-      auto DRE = dyn_cast<DeclRefExpr>(call->getSemanticFn());
+      // We only care about binary expressions.
+      if (!isa<BinaryExpr>(call)) return;
+
+      // Dig out the function we're calling.
+      auto fnExpr = call->getSemanticFn();
+      if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(fnExpr))
+        fnExpr = dotSyntax->getSemanticFn();
+
+      auto DRE = dyn_cast<DeclRefExpr>(fnExpr);
       auto args = dyn_cast<TupleExpr>(call->getArg());
       if (!DRE || !DRE->getDecl()->isOperator() ||
           !args || args->getNumElements() != 2)
@@ -3724,21 +3732,12 @@
   if (params->size() != 0 && !params->get(0)->getName().empty())
     firstParamName = params->get(0)->getName().str();
 
-  // Find the set of property names.
-  const InheritedNameSet *allPropertyNames = nullptr;
-  if (contextType) {
-    if (auto classDecl = contextType->getClassOrBoundGenericClass()) {
-      allPropertyNames = Context.getAllPropertyNames(classDecl,
-                                                     afd->isInstanceMember());
-    }
-  }
-
   StringScratchSpace scratch;
   if (!swift::omitNeedlessWords(baseNameStr, argNameStrs, firstParamName,
                                 getTypeNameForOmission(resultType),
                                 getTypeNameForOmission(contextType),
                                 paramTypes, returnsSelf, false,
-                                allPropertyNames, scratch))
+                                /*allPropertyNames=*/nullptr, scratch))
     return None;
 
   /// Retrieve a replacement identifier.
@@ -3790,23 +3789,13 @@
   while (auto optObjectTy = type->getAnyOptionalObjectType())
     type = optObjectTy;
 
-  // Find the set of property names.
-  const InheritedNameSet *allPropertyNames = nullptr;
-  if (contextType) {
-    if (auto classDecl = contextType->getClassOrBoundGenericClass()) {
-      allPropertyNames = Context.getAllPropertyNames(classDecl,
-                                                     var->isInstanceMember());
-    }
-  }
-
-
   // Omit needless words.
   StringScratchSpace scratch;
   OmissionTypeName typeName = getTypeNameForOmission(var->getInterfaceType());
   OmissionTypeName contextTypeName = getTypeNameForOmission(contextType);
   if (::omitNeedlessWords(name, { }, "", typeName, contextTypeName, { },
-                          /*returnsSelf=*/false, true, allPropertyNames,
-                          scratch)) {
+                          /*returnsSelf=*/false, true,
+                          /*allPropertyNames=*/nullptr, scratch)) {
     return Context.getIdentifier(name);
   }
 
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index c10325c..6d70db7 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -79,6 +79,7 @@
   IGNORED_ATTR(FixedLayout)
   IGNORED_ATTR(Infix)
   IGNORED_ATTR(Inline)
+  IGNORED_ATTR(Optimize)
   IGNORED_ATTR(Inlineable)
   IGNORED_ATTR(NSApplicationMain)
   IGNORED_ATTR(NSCopying)
@@ -279,7 +280,9 @@
   if (auto *VD = dyn_cast<VarDecl>(D)) {
     // Stored properties and variables can't be transparent.
     if (VD->hasStorage())
-      return diagnoseAndRemoveAttr(attr, diag::transparent_stored_property);
+      return diagnoseAndRemoveAttr(attr,
+                                   diag::attribute_invalid_on_stored_property,
+                                   attr->getAttrName());
   }
 }
 
@@ -866,7 +869,8 @@
   void visitFixedLayoutAttr(FixedLayoutAttr *attr);
   void visitVersionedAttr(VersionedAttr *attr);
   void visitInlineableAttr(InlineableAttr *attr);
-  
+  void visitOptimizeAttr(OptimizeAttr *attr);
+
   void visitDiscardableResultAttr(DiscardableResultAttr *attr);
   void visitImplementsAttr(ImplementsAttr *attr);
 };
@@ -1914,7 +1918,8 @@
   if (auto *VD = dyn_cast<VarDecl>(D)) {
     if (VD->hasStorage() || VD->getAttrs().hasAttribute<LazyAttr>()) {
       TC.diagnose(attr->getLocation(),
-                  diag::inlineable_stored_property)
+                  diag::attribute_invalid_on_stored_property,
+                  attr->getAttrName())
         .fixItRemove(attr->getRangeWithAt());
       attr->setInvalid();
       return;
@@ -1947,6 +1952,19 @@
   }
 }
 
+void AttributeChecker::visitOptimizeAttr(OptimizeAttr *attr) {
+  if (auto *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->hasStorage()) {
+      TC.diagnose(attr->getLocation(),
+                  diag::attribute_invalid_on_stored_property,
+                  attr->getAttrName())
+      .fixItRemove(attr->getRangeWithAt());
+      attr->setInvalid();
+      return;
+    }
+  }
+}
+
 void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
   if (auto *FD = dyn_cast<FuncDecl>(D)) {
     if (auto result = FD->getResultInterfaceType()) {
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index 9a42ad4..3025c13 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -1499,6 +1499,27 @@
                                   IsUnavailable);
 }
 
+bool TypeChecker::isInsideCompatibleUnavailableDeclaration(
+    SourceRange ReferenceRange, const DeclContext *ReferenceDC,
+    const AvailableAttr *attr) {
+  if (!attr->isUnconditionallyUnavailable()) {
+    return false;
+  }
+  PlatformKind platform = attr->Platform;
+  if (platform == PlatformKind::none) {
+    return false;
+  }
+
+  auto IsUnavailable = [platform](const Decl *D) {
+    auto EnclosingUnavailable =
+        D->getAttrs().getUnavailable(D->getASTContext());
+    return EnclosingUnavailable && EnclosingUnavailable->Platform == platform;
+  };
+
+  return someEnclosingDeclMatches(ReferenceRange, ReferenceDC, *this,
+                                  IsUnavailable);
+}
+
 bool TypeChecker::isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
                                                 const DeclContext *ReferenceDC){
   auto IsDeprecated = [](const Decl *D) {
@@ -2093,6 +2114,14 @@
     return false;
   }
 
+  // Calling unavailable code from within code with the same
+  // unavailability is OK -- the eventual caller can't call the
+  // enclosing code in the same situations it wouldn't be able to
+  // call this code.
+  if (isInsideCompatibleUnavailableDeclaration(R, DC, Attr)) {
+    return false;
+  }
+
   SourceLoc Loc = R.Start;
   auto Name = D->getFullName();
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 55aa7a8..62f9cb5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2086,16 +2086,34 @@
     checkGenericParamAccess(TC, CD->getGenericParams(), CD);
 
     if (CD->hasSuperclass()) {
-      Type superclass = CD->getSuperclass();
+      const NominalTypeDecl *superclassDecl =
+          CD->getSuperclass()->getAnyNominal();
+      // Be slightly defensive here in the presence of badly-ordered
+      // inheritance clauses.
       auto superclassLocIter = std::find_if(CD->getInherited().begin(),
                                             CD->getInherited().end(),
                                             [&](TypeLoc inherited) {
         if (!inherited.wasValidated())
           return false;
-        return inherited.getType().getPointer() == superclass.getPointer();
+        Type ty = inherited.getType();
+        if (ty->is<ProtocolCompositionType>())
+          ty = ty->getExistentialLayout().superclass;
+        return ty->getAnyNominal() == superclassDecl;
       });
+      // Sanity check: we couldn't find the superclass for whatever reason
+      // (possibly because it's synthetic or something), so don't bother
+      // checking it.
       if (superclassLocIter == CD->getInherited().end())
         return;
+
+      auto outerDowngradeToWarning = DowngradeToWarning::No;
+      if (superclassDecl->isGenericContext() &&
+          !TC.getLangOpts().isSwiftVersionAtLeast(5)) {
+        // Swift 4 failed to properly check this if the superclass was generic,
+        // because the above loop was too strict.
+        outerDowngradeToWarning = DowngradeToWarning::Yes;
+      }
+
       checkTypeAccess(TC, *superclassLocIter, CD,
                       [&](AccessScope typeAccessScope,
                           const TypeRepr *complainRepr,
@@ -2103,8 +2121,10 @@
         auto typeAccess = typeAccessScope.accessLevelForDiagnostics();
         bool isExplicit = CD->getAttrs().hasAttribute<AccessControlAttr>();
         auto diagID = diag::class_super_access;
-        if (downgradeToWarning == DowngradeToWarning::Yes)
+        if (downgradeToWarning == DowngradeToWarning::Yes ||
+            outerDowngradeToWarning == DowngradeToWarning::Yes) {
           diagID = diag::class_super_access_warn;
+        }
         auto diag = TC.diagnose(CD, diagID, isExplicit, CD->getFormalAccess(),
                                 typeAccess,
                                 isa<FileUnit>(CD->getDeclContext()));
@@ -4618,7 +4638,7 @@
     if (!IsFirstPass)
       TC.addImplicitConstructors(CD);
 
-    TC.addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
 
     if (!IsFirstPass && !CD->isInvalid())
       TC.checkConformancesInContext(CD, CD);
@@ -6361,6 +6381,7 @@
     UNINTERESTING_ATTR(IBOutlet)
     UNINTERESTING_ATTR(Indirect)
     UNINTERESTING_ATTR(Inline)
+    UNINTERESTING_ATTR(Optimize)
     UNINTERESTING_ATTR(Inlineable)
     UNINTERESTING_ATTR(Effects)
     UNINTERESTING_ATTR(FixedLayout)
@@ -7192,13 +7213,7 @@
            && "Decl parsing must prevent destructors outside of types!");
 
     TC.checkDeclAttributesEarly(DD);
-    if (!DD->hasAccess()) {
-      DD->setAccess(enclosingClass->getFormalAccess());
-    }
-
-    if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
-      DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
-    }
+    DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
 
     configureImplicitSelf(TC, DD);
 
@@ -7871,7 +7886,11 @@
 }
 
 void TypeChecker::requestClassLayout(ClassDecl *classDecl) {
-  // FIXME: Check a flag in the class...
+  if (classDecl->hasValidatedLayout())
+    return;
+
+  classDecl->setHasValidatedLayout();
+
   if (isa<SourceFile>(classDecl->getModuleScopeContext()))
     DeclsToFinalize.insert(classDecl);
 }
@@ -7938,7 +7957,7 @@
   // class, you shouldn't have to know what the vtable layout is.
   if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
     TC.addImplicitConstructors(CD);
-    TC.addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
   }
 
   // validateDeclForNameLookup will not trigger an immediate full
@@ -8045,9 +8064,6 @@
   if (auto unbound = type->getAs<UnboundGenericType>()) {
     parentType = unbound->getParent();
     nominal = cast<NominalTypeDecl>(unbound->getDecl());
-  } else if (auto bound = type->getAs<BoundGenericType>()) {
-    parentType = bound->getParent();
-    nominal = bound->getDecl();
   } else {
     auto nominalType = type->castTo<NominalType>();
     parentType = nominalType->getParent();
@@ -8140,15 +8156,6 @@
   return { env, extContextType };
 }
 
-// FIXME: In TypeChecker.cpp; only needed because LLDB creates
-// extensions of typealiases to unbound generic types, which is
-// ill-formed but convenient.
-namespace swift {
-GenericParamList *cloneGenericParams(ASTContext &ctx,
-                                     DeclContext *dc,
-                                     GenericParamList *fromParams);
-} // namespace swift
-
 void TypeChecker::validateExtension(ExtensionDecl *ext) {
   // If we're currently validating, or have already validated this extension,
   // there's nothing more to do now.
@@ -8176,56 +8183,23 @@
   if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
     requestClassLayout(classDecl);
 
-  if (extendedType->hasUnboundGenericType()) {
+  if (nominal->getGenericParamsOfContext()) {
     auto genericParams = ext->getGenericParams();
-
-    // The debugger synthesizes typealiases of unbound generic types
-    // to produce its extensions, which subverts bindExtensionDecl's
-    // ability to create the generic parameter lists. Create the list now.
-    if (!genericParams && Context.LangOpts.DebuggerSupport) {
-      genericParams = cloneGenericParams(Context, ext,
-                                         nominal->getGenericParams());
-      ext->setGenericParams(genericParams);
-    }
     assert(genericParams && "bindExtensionDecl didn't set generic params?");
 
     // Check generic parameters.
     GenericEnvironment *env;
     std::tie(env, extendedType) = checkExtensionGenericParams(
-        *this, ext, ext->getExtendedType(), ext->getGenericParams());
+        *this, ext, ext->getExtendedType()->getCanonicalType(),
+        genericParams);
 
     ext->getExtendedTypeLoc().setType(extendedType);
     ext->setGenericEnvironment(env);
     return;
   }
-  
-  // If we're extending a protocol, check the generic parameters.
-  //
-  // Canonicalize the type to work around the fact that getAs<> cannot
-  // "look through" protocol<X, Y> where X and Y both desugar to the same
-  // thing.
-  //
-  // FIXME: Probably the above comes up elsewhere, perhaps getAs<>()
-  // should be fixed.
-  if (auto proto = extendedType->getCanonicalType()->getAs<ProtocolType>()) {
-    GenericEnvironment *env;
-    std::tie(env, extendedType) =
-        checkExtensionGenericParams(*this, ext, proto, ext->getGenericParams());
-
-    ext->getExtendedTypeLoc().setType(extendedType);
-    ext->setGenericEnvironment(env);
-    return;
-  }
-
-  // If the nominal type has a generic signature that we didn't otherwise
-  // handle yet, use it directly.
-  if (auto genericSig = nominal->getGenericSignature()) {
-    auto genericEnv = genericSig->createGenericEnvironment();
-    ext->setGenericEnvironment(genericEnv);
-    return;
-  }
 
   assert(extendedType->is<NominalType>());
+  assert(!nominal->isGenericContext());
 }
 
 llvm::TinyPtrVector<ProtocolDecl *>
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f53508b..0cdbf53 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2348,25 +2348,14 @@
   // Replace generic type parameters and associated types with their
   // witnesses, when we have them.
   auto selfTy = conformance->getProtocol()->getSelfInterfaceType();
-  type = type.transform([&](Type type) -> Type {
-    // If a dependent member refers to an associated type, replace it.
-    if (auto member = type->getAs<DependentMemberType>()) {
-      if (member->getBase()->isEqual(selfTy)) {
-        // FIXME: Could handle inherited conformances here.
-        if (conformance->hasTypeWitness(member->getAssocType()))
-          return conformance->getTypeWitness(member->getAssocType(), nullptr);
-      }
-    }
+  return type.subst([&](SubstitutableType *dependentType) {
+                      if (dependentType->isEqual(selfTy))
+                        return conformance->getType();
 
-    // Replace 'Self' with the conforming type.
-    if (type->isEqual(selfTy))
-      return conformance->getType();
-
-    return type;
-  });
-
-  //
-  return type;
+                      return Type(dependentType);
+                    },
+                    LookUpConformanceInModule(module),
+                    SubstFlags::UseErrorType);
 }
 
 /// \brief Retrieve the kind of requirement described by the given declaration,
@@ -6356,6 +6345,24 @@
   return false;
 }
 
+/// Determine whether this is an unlabeled initializer or subscript.
+static bool isUnlabeledInitializerOrSubscript(ValueDecl *value) {
+  ParameterList *paramList = nullptr;
+  if (auto constructor = dyn_cast<ConstructorDecl>(value))
+    paramList = constructor->getParameterList(1);
+  else if (auto subscript = dyn_cast<SubscriptDecl>(value))
+    paramList = subscript->getIndices();
+  else
+    return false;
+
+  for (auto param : *paramList) {
+    if (!param->getArgumentName().empty()) return false;
+  }
+
+  return true;
+}
+
+/// Determine whether this declaration is an initializer
 /// Determine whether we should warn about the given witness being a close
 /// match for the given optional requirement.
 static bool shouldWarnAboutPotentialWitness(
@@ -6390,6 +6397,12 @@
       if (!attr->isImplicit()) return false;
   }
 
+  // Don't warn if the requirement or witness is an initializer or subscript
+  // with no argument labels.
+  if (isUnlabeledInitializerOrSubscript(req) ||
+      isUnlabeledInitializerOrSubscript(witness))
+    return false;
+
   // If the score is relatively high, don't warn: this is probably
   // unrelated.  Allow about one typo for every four properly-typed
   // characters, which prevents completely-wacky suggestions in many
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 9cd8bd7..9aa42f8 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1702,17 +1702,25 @@
                                 TypeResolutionOptions options,
                                 FunctionType::ExtInfo extInfo
                                   = FunctionType::ExtInfo());
-    Type resolveSILFunctionType(
-        FunctionTypeRepr *repr, TypeResolutionOptions options,
-        SILFunctionType::ExtInfo extInfo = SILFunctionType::ExtInfo(),
-        ParameterConvention calleeConvention = DefaultParameterConvention,
-        TypeRepr *witnessmethodProtocol = nullptr);
+    Type resolveSILFunctionType(FunctionTypeRepr *repr,
+                                TypeResolutionOptions options,
+                                SILCoroutineKind coroutineKind
+                                  = SILCoroutineKind::None,
+                                SILFunctionType::ExtInfo extInfo
+                                  = SILFunctionType::ExtInfo(),
+                                ParameterConvention calleeConvention
+                                  = DefaultParameterConvention,
+                                TypeRepr *witnessmethodProtocol = nullptr);
     SILParameterInfo resolveSILParameter(TypeRepr *repr,
                                          TypeResolutionOptions options);
+    SILYieldInfo resolveSILYield(TypeAttributes &remainingAttrs,
+                                 TypeRepr *repr, TypeResolutionOptions options);
     bool resolveSILResults(TypeRepr *repr, TypeResolutionOptions options,
+                           SmallVectorImpl<SILYieldInfo> &yields,
                            SmallVectorImpl<SILResultInfo> &results,
                            Optional<SILResultInfo> &errorResult);
     bool resolveSingleSILResult(TypeRepr *repr, TypeResolutionOptions options,
+                                SmallVectorImpl<SILYieldInfo> &yields,
                                 SmallVectorImpl<SILResultInfo> &results,
                                 Optional<SILResultInfo> &errorResult);
     Type resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
@@ -1970,7 +1978,7 @@
   static const TypeAttrKind FunctionAttrs[] = {
     TAK_convention, TAK_noreturn, TAK_pseudogeneric,
     TAK_callee_owned, TAK_callee_guaranteed, TAK_noescape, TAK_autoclosure,
-    TAK_escaping
+    TAK_escaping, TAK_yield_once, TAK_yield_many
   };
 
   auto checkUnsupportedAttr = [&](TypeAttrKind attr) {
@@ -2018,6 +2026,13 @@
     SILFunctionType::Representation rep;
     TypeRepr *witnessMethodProtocol = nullptr;
 
+    auto coroutineKind = SILCoroutineKind::None;
+    if (attrs.has(TAK_yield_once)) {
+      coroutineKind = SILCoroutineKind::YieldOnce;
+    } else if (attrs.has(TAK_yield_many)) {
+      coroutineKind = SILCoroutineKind::YieldMany;
+    }
+
     auto calleeConvention = ParameterConvention::Direct_Unowned;
     if (attrs.has(TAK_callee_owned)) {
       if (attrs.has(TAK_callee_guaranteed)) {
@@ -2065,7 +2080,8 @@
     SILFunctionType::ExtInfo extInfo(rep, attrs.has(TAK_pseudogeneric),
                                      attrs.has(TAK_noescape));
 
-    ty = resolveSILFunctionType(fnRepr, options, extInfo, calleeConvention,
+    ty = resolveSILFunctionType(fnRepr, options, coroutineKind,
+                                extInfo, calleeConvention,
                                 witnessMethodProtocol);
     if (!ty || ty->hasError()) return ty;
   } else if (hasFunctionAttr) {
@@ -2257,6 +2273,11 @@
   options -= TR_ImmediateFunctionInput;
   options -= TR_FunctionInput;
   options -= TR_TypeAliasUnderlyingType;
+  // FIXME: Until we remove the IUO type from the type system, we
+  // need to continue to parse IUOs in SIL tests so that we can
+  // match the types we generate from the importer.
+  if (!options.contains(TR_SILMode))
+    options -= TR_AllowIUO;
 
   Type inputTy = resolveType(repr->getArgsTypeRepr(),
                              options | TR_ImmediateFunctionInput);
@@ -2424,6 +2445,7 @@
 
 Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
                                           TypeResolutionOptions options,
+                                          SILCoroutineKind coroutineKind,
                                           SILFunctionType::ExtInfo extInfo,
                                           ParameterConvention callee,
                                           TypeRepr *witnessMethodProtocol) {
@@ -2436,6 +2458,7 @@
   // Resolve parameter and result types using the function's generic
   // environment.
   SmallVector<SILParameterInfo, 4> params;
+  SmallVector<SILYieldInfo, 4> yields;
   SmallVector<SILResultInfo, 4> results;
   Optional<SILResultInfo> errorResult;
   {
@@ -2484,10 +2507,17 @@
 
     {
       // FIXME: Deal with unsatisfied dependencies.
-      if (resolveSILResults(repr->getResultTypeRepr(), options,
+      if (resolveSILResults(repr->getResultTypeRepr(), options, yields,
                             results, errorResult)) {
         hasError = true;
       }
+
+      // Diagnose non-coroutines that declare yields.
+      if (coroutineKind == SILCoroutineKind::None && !yields.empty()) {
+        TC.diagnose(repr->getResultTypeRepr()->getLoc(),
+                    diag::sil_non_coro_yields);
+        hasError = true;
+      }
     }
   } // restore generic type resolver
 
@@ -2498,6 +2528,7 @@
   // FIXME: Remap the parsed context types to interface types.
   CanGenericSignature genericSig;
   SmallVector<SILParameterInfo, 4> interfaceParams;
+  SmallVector<SILYieldInfo, 4> interfaceYields;
   SmallVector<SILResultInfo, 4> interfaceResults;
   Optional<SILResultInfo> interfaceErrorResult;
   if (auto *genericEnv = repr->getGenericEnvironment()) {
@@ -2508,6 +2539,11 @@
           param.getType())->getCanonicalType();
       interfaceParams.push_back(param.getWithType(transParamType));
     }
+    for (auto &yield : yields) {
+      auto transYieldType = genericEnv->mapTypeOutOfContext(
+          yield.getType())->getCanonicalType();
+      interfaceYields.push_back(yield.getWithType(transYieldType));
+    }
     for (auto &result : results) {
       auto transResultType = genericEnv->mapTypeOutOfContext(
           result.getType())->getCanonicalType();
@@ -2522,6 +2558,7 @@
     }
   } else {
     interfaceParams = params;
+    interfaceYields = yields;
     interfaceResults = results;
     interfaceErrorResult = errorResult;
   }
@@ -2552,9 +2589,20 @@
            "found witness_method without matching conformance");
   }
 
-  return SILFunctionType::get(genericSig, extInfo, callee, interfaceParams,
-                              interfaceResults, interfaceErrorResult, Context,
-                              witnessMethodConformance);
+  return SILFunctionType::get(genericSig, extInfo, coroutineKind,
+                              callee,
+                              interfaceParams, interfaceYields,
+                              interfaceResults, interfaceErrorResult,
+                              Context, witnessMethodConformance);
+}
+
+SILYieldInfo TypeResolver::resolveSILYield(TypeAttributes &attrs,
+                                           TypeRepr *repr,
+                                           TypeResolutionOptions options) {
+  AttributedTypeRepr attrRepr(attrs, repr);
+  SILParameterInfo paramInfo =
+    resolveSILParameter(&attrRepr, options | TR_ImmediateFunctionInput);
+  return SILYieldInfo(paramInfo.getType(), paramInfo.getConvention());
 }
 
 SILParameterInfo TypeResolver::resolveSILParameter(
@@ -2568,6 +2616,7 @@
 
   if (auto attrRepr = dyn_cast<AttributedTypeRepr>(repr)) {
     auto attrs = attrRepr->getAttrs();
+
     auto checkFor = [&](TypeAttrKind tak, ParameterConvention attrConv) {
       if (!attrs.has(tak)) return;
       if (convention != DefaultParameterConvention) {
@@ -2610,6 +2659,7 @@
 
 bool TypeResolver::resolveSingleSILResult(TypeRepr *repr,
                                           TypeResolutionOptions options,
+                                          SmallVectorImpl<SILYieldInfo> &yields,
                               SmallVectorImpl<SILResultInfo> &ordinaryResults,
                                        Optional<SILResultInfo> &errorResult) {
   Type type;
@@ -2620,6 +2670,19 @@
     // Copy the attributes out; we're going to destructively modify them.
     auto attrs = attrRepr->getAttrs();
 
+    // Recognize @yields.
+    if (attrs.has(TypeAttrKind::TAK_yields)) {
+      attrs.clearAttribute(TypeAttrKind::TAK_yields);
+
+      // The treatment from this point on is basically completely different.
+      auto yield = resolveSILYield(attrs, attrRepr->getTypeRepr(), options);
+      if (yield.getType()->hasError())
+        return true;
+
+      yields.push_back(yield);
+      return false;
+    }
+
     // Recognize @error.
     if (attrs.has(TypeAttrKind::TAK_error)) {
       attrs.clearAttribute(TypeAttrKind::TAK_error);
@@ -2687,6 +2750,7 @@
 
 bool TypeResolver::resolveSILResults(TypeRepr *repr,
                                      TypeResolutionOptions options,
+                                SmallVectorImpl<SILYieldInfo> &yields,
                                 SmallVectorImpl<SILResultInfo> &ordinaryResults,
                                 Optional<SILResultInfo> &errorResult) {
   if (auto tuple = dyn_cast<TupleTypeRepr>(repr)) {
@@ -2696,13 +2760,15 @@
         TC.diagnose(element.UnderscoreLoc, diag::sil_function_output_label);
     }
     for (auto elt : tuple->getElements()) {
-      if (resolveSingleSILResult(elt.Type, options, ordinaryResults, errorResult))
+      if (resolveSingleSILResult(elt.Type, options,
+                                 yields, ordinaryResults, errorResult))
         hadError = true;
     }
     return hadError;
   }
 
-  return resolveSingleSILResult(repr, options, ordinaryResults, errorResult);
+  return resolveSingleSILResult(repr, options,
+                                yields, ordinaryResults, errorResult);
 }
 
 Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index eb3f643..b75df46 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -69,7 +69,7 @@
     addImplicitStructConformances(SD);
   }
   if (auto CD = dyn_cast<ClassDecl>(decl)) {
-    addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
   }
   if (auto ED = dyn_cast<EnumDecl>(decl)) {
     addImplicitEnumConformances(ED);
@@ -261,13 +261,11 @@
   return *boolType;
 }
 
-namespace swift {
-
 /// Clone the given generic parameters in the given list. We don't need any
 /// of the requirements, because they will be inferred.
-GenericParamList *cloneGenericParams(ASTContext &ctx,
-                                     DeclContext *dc,
-                                     GenericParamList *fromParams) {
+static GenericParamList *cloneGenericParams(ASTContext &ctx,
+                                            DeclContext *dc,
+                                            GenericParamList *fromParams) {
   // Clone generic parameters.
   SmallVector<GenericTypeParamDecl *, 2> toGenericParams;
   for (auto fromGP : *fromParams) {
@@ -292,12 +290,6 @@
 
   return toParams;
 }
-} // namespace swift
-
-// FIXME: total hack
-GenericParamList *createProtocolGenericParams(ASTContext &ctx,
-                                              ProtocolDecl *proto,
-                                              DeclContext *dc);
 
 static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
   if (ED->getExtendedType())
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index bf862ae..fa1ecae 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -741,12 +741,6 @@
   /// will need to compute captures for.
   std::vector<AnyFunctionRef> ClosuresWithUncomputedCaptures;
 
-  /// Describes an attempt to capture a local function.
-  struct LocalFunctionCapture {
-    FuncDecl *LocalFunction;
-    SourceLoc CaptureLoc;
-  };
-
   /// Local functions that have been captured before their definitions.
   ///
   /// We need this to guard against functions that would transitively capture
@@ -1517,10 +1511,6 @@
   /// struct or class.
   void addImplicitConstructors(NominalTypeDecl *typeDecl);
 
-  /// \brief Add an implicitly-defined destructor, if there is no
-  /// user-provided destructor.
-  void addImplicitDestructor(ClassDecl *CD);
-
   /// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
   /// imported NS_OPTIONS struct.
   void addImplicitStructConformances(StructDecl *ED);
@@ -2376,6 +2366,12 @@
   bool isInsideUnavailableDeclaration(SourceRange ReferenceRange,
                                       const DeclContext *DC);
 
+  /// Returns true if the reference or any of its parents is an
+  /// unconditional unavailable declaration for the same platform.
+  bool isInsideCompatibleUnavailableDeclaration(SourceRange ReferenceRange,
+                                                const DeclContext *DC,
+                                                const AvailableAttr *attr);
+
   /// Returns true if the reference is lexically contained in a declaration
   /// that is deprecated on all deployment targets.
   bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 68890a2..0918a5b 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -439,9 +439,11 @@
   unsigned kind = Cursor.readRecord(next.ID, scratch);
   switch (kind) {
   case decls_block::SIL_LAYOUT: {
+    GenericSignatureID rawGenericSig;
     unsigned numFields;
     ArrayRef<uint64_t> types;
-    decls_block::SILLayoutLayout::readRecord(scratch, numFields, types);
+    decls_block::SILLayoutLayout::readRecord(scratch, rawGenericSig,
+                                             numFields, types);
     
     SmallVector<SILField, 4> fields;
     for (auto fieldInfo : types.slice(0, numFields)) {
@@ -452,20 +454,10 @@
                  isMutable));
     }
     
-    SmallVector<GenericTypeParamType*, 4> genericParams;
-    for (auto typeId : types.slice(numFields)) {
-      auto type = getType(typeId)->castTo<GenericTypeParamType>();
-      genericParams.push_back(type);
-    }
-    
-    SmallVector<Requirement, 4> requirements;
-    readGenericRequirements(requirements, DeclTypeCursor);
-    CanGenericSignature sig;
-    if (!genericParams.empty() || !requirements.empty()) {
-      sig = GenericSignature::get(genericParams, requirements)
-        ->getCanonicalSignature();
-    }
-    return SILLayout::get(getContext(), sig, fields);
+    CanGenericSignature canSig;
+    if (auto sig = getGenericSignature(rawGenericSig))
+      canSig = sig->getCanonicalSignature();
+    return SILLayout::get(getContext(), canSig, fields);
   }
   default:
     error();
@@ -920,6 +912,68 @@
   }
 }
 
+GenericSignature *ModuleFile::getGenericSignature(
+                                      serialization::GenericSignatureID ID) {
+  using namespace decls_block;
+
+  // Zero is a sentinel for having no generic signature.
+  if (ID == 0) return nullptr;
+
+  assert(ID <= GenericSignatures.size() && "invalid GenericSignature ID");
+  auto &sigOrOffset = GenericSignatures[ID-1];
+
+  // If we've already deserialized this generic signature, return it.
+  if (sigOrOffset.isComplete()) {
+    return sigOrOffset.get();
+  }
+
+  // Read the generic signature.
+  BCOffsetRAII restoreOffset(DeclTypeCursor);
+  DeclTypeCursor.JumpToBit(sigOrOffset);
+  DeserializingEntityRAII deserializingEntity(*this);
+
+  // Read the parameter types.
+  SmallVector<GenericTypeParamType *, 4> paramTypes;
+  StringRef blobData;
+  SmallVector<uint64_t, 8> scratch;
+
+  auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
+  if (entry.Kind != llvm::BitstreamEntry::Record) {
+    error();
+    return nullptr;
+  }
+
+  unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
+  if (recordID != GENERIC_SIGNATURE) {
+    error();
+    return nullptr;
+  }
+
+  ArrayRef<uint64_t> rawParamIDs;
+  GenericSignatureLayout::readRecord(scratch, rawParamIDs);
+
+  for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
+    auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
+    paramTypes.push_back(paramTy);
+  }
+
+  // Read the generic requirements.
+  SmallVector<Requirement, 4> requirements;
+  readGenericRequirements(requirements, DeclTypeCursor);
+
+  // Construct the generic signature from the loaded parameters and
+  // requirements.
+  auto signature = GenericSignature::get(paramTypes, requirements);
+
+  // If we've already deserialized this generic signature, return it.
+  if (sigOrOffset.isComplete()) {
+    return sigOrOffset.get();
+  }
+
+  sigOrOffset = signature;
+  return signature;
+}
+
 llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
 ModuleFile::getGenericSignatureOrEnvironment(
                                          serialization::GenericEnvironmentID ID,
@@ -940,13 +994,21 @@
     return envOrOffset.get();
   }
 
-  // Read the generic environment.
-  BCOffsetRAII restoreOffset(DeclTypeCursor);
-  DeclTypeCursor.JumpToBit(envOrOffset);
-  DeserializingEntityRAII deserializingEntity(*this);
+  // Extract the bit offset or generic signature ID.
+  uint64_t bitOffset = envOrOffset;
+  GenericSignature *signature = nullptr;
+  if (bitOffset & 0x01) {
+    // We have a generic signature ID.
+    signature = getGenericSignature(bitOffset >> 1);
+  } else {
+    bitOffset = bitOffset >> 1;
 
-  SmallVector<GenericTypeParamType *, 4> paramTypes;
-  {
+    // Read the generic environment.
+    BCOffsetRAII restoreOffset(DeclTypeCursor);
+    DeclTypeCursor.JumpToBit(bitOffset);
+    DeserializingEntityRAII deserializingEntity(*this);
+
+    SmallVector<GenericTypeParamType *, 4> paramTypes;
     using namespace decls_block;
 
     StringRef blobData;
@@ -963,72 +1025,55 @@
       return result;
 
     unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
-    switch (recordID) {
-    case GENERIC_ENVIRONMENT: {
-      lastRecordOffset.reset();
-
-      ArrayRef<uint64_t> rawParamIDs;
-      GenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
-
-      for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
-        auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
-        paramTypes.push_back(paramTy);
-      }
-      break;
-    }
-
-    case SIL_GENERIC_ENVIRONMENT: {
-      ArrayRef<uint64_t> rawParamIDs;
-      SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
-      lastRecordOffset.reset();
-
-      if (rawParamIDs.size() % 2 != 0) {
-        error();
-        return result;
-      }
-
-      for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
-        Identifier name = getIdentifier(rawParamIDs[i]);
-        auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
-
-        if (!name.empty()) {
-          auto paramDecl =
-            createDecl<GenericTypeParamDecl>(getAssociatedModule(),
-                                             name,
-                                             SourceLoc(),
-                                             paramTy->getDepth(),
-                                             paramTy->getIndex());
-          paramTy = paramDecl->getDeclaredInterfaceType()
-                     ->castTo<GenericTypeParamType>();
-        }
-
-        paramTypes.push_back(paramTy);
-      }
-      break;
-    }
-
-    default:
+    if (recordID != SIL_GENERIC_ENVIRONMENT) {
       error();
       return result;
     }
+
+    ArrayRef<uint64_t> rawParamIDs;
+    SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
+    lastRecordOffset.reset();
+
+    if (rawParamIDs.size() % 2 != 0) {
+      error();
+      return result;
+    }
+
+    for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
+      Identifier name = getIdentifier(rawParamIDs[i]);
+      auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
+
+      if (!name.empty()) {
+        auto paramDecl =
+          createDecl<GenericTypeParamDecl>(getAssociatedModule(),
+                                           name,
+                                           SourceLoc(),
+                                           paramTy->getDepth(),
+                                           paramTy->getIndex());
+        paramTy = paramDecl->getDeclaredInterfaceType()
+                   ->castTo<GenericTypeParamType>();
+      }
+
+      paramTypes.push_back(paramTy);
+    }
+
+    // If there are no parameters, the environment is empty.
+    if (paramTypes.empty()) {
+      if (wantEnvironment)
+        envOrOffset = nullptr;
+
+      return result;
+    }
+
+    // Read the generic requirements.
+    SmallVector<Requirement, 4> requirements;
+    readGenericRequirements(requirements, DeclTypeCursor);
+
+    // Construct the generic signature from the loaded parameters and
+    // requirements.
+    signature = GenericSignature::get(paramTypes, requirements);
   }
 
-  // If there are no parameters, the environment is empty.
-  if (paramTypes.empty()) {
-    if (wantEnvironment)
-      envOrOffset = nullptr;
-
-    return result;
-  }
-
-  // Read the generic requirements.
-  SmallVector<Requirement, 4> requirements;
-  readGenericRequirements(requirements, DeclTypeCursor);
-
-  // Construct the generic signature from the loaded parameters and
-  // requirements.
-  auto signature = GenericSignature::get(paramTypes, requirements);
-
   // If we only want the signature, return it now.
   if (!wantEnvironment) return signature;
 
@@ -1232,9 +1277,18 @@
     DeclBaseName name = getDeclBaseName(IID);
     pathTrace.addValue(name);
 
-    Type filterTy = getType(TID);
-    if (!isType)
+    Type filterTy;
+    if (!isType) {
+      auto maybeType = getTypeChecked(TID);
+      if (!maybeType) {
+        // FIXME: Don't throw away the inner error's information.
+        llvm::consumeError(maybeType.takeError());
+        return llvm::make_error<XRefError>("couldn't decode type",
+                                           pathTrace, name);
+      }
+      filterTy = maybeType.get();
       pathTrace.addType(filterTy);
+    }
 
     baseModule->lookupQualified(ModuleType::get(baseModule), name,
                                 NL_QualifiedDefault | NL_KnownNoDependency,
@@ -1437,9 +1491,18 @@
 
       pathTrace.addValue(memberName);
 
-      Type filterTy = getType(TID);
-      if (!isType)
+      Type filterTy;
+      if (!isType) {
+        auto maybeType = getTypeChecked(TID);
+        if (!maybeType) {
+          // FIXME: Don't throw away the inner error's information.
+          llvm::consumeError(maybeType.takeError());
+          return llvm::make_error<XRefError>("couldn't decode type",
+                                             pathTrace, memberName);
+        }
+        filterTy = maybeType.get();
         pathTrace.addType(filterTy);
+      }
 
       if (values.size() != 1) {
         return llvm::make_error<XRefError>("multiple matching base values",
@@ -1465,23 +1528,13 @@
 
     case XREF_EXTENSION_PATH_PIECE: {
       ModuleID ownerID;
-      ArrayRef<uint64_t> genericParamIDs;
-      XRefExtensionPathPieceLayout::readRecord(scratch, ownerID,
-                                               genericParamIDs);
+      GenericSignatureID rawGenericSig;
+      XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
       M = getModule(ownerID);
       pathTrace.addExtension(M);
 
       // Read the generic signature, if we have one.
-      if (!genericParamIDs.empty()) {
-        SmallVector<GenericTypeParamType *, 4> params;
-        SmallVector<Requirement, 5> requirements;
-        for (TypeID paramID : genericParamIDs) {
-          params.push_back(getType(paramID)->castTo<GenericTypeParamType>());
-        }
-        readGenericRequirements(requirements, DeclTypeCursor);
-
-        genericSig = GenericSignature::getCanonical(params, requirements);
-      }
+      genericSig = CanGenericSignature(getGenericSignature(rawGenericSig));
 
       continue;
     }
@@ -2113,7 +2166,10 @@
   Expected<Decl *> deserialized = getDeclCheckedImpl(DID, ForcedContext);
   if (deserialized && deserialized.get()) {
     if (auto *IDC = dyn_cast<IterableDeclContext>(deserialized.get())) {
-      if (IDC->wasDeserialized()) {
+      // Only set the DeclID on the returned Decl if it's one that was loaded
+      // and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
+      if (IDC->wasDeserialized() &&
+          static_cast<uint32_t>(IDC->getDeclID()) == 0) {
         IDC->setDeclID(DID);
       }
     }
@@ -2280,6 +2336,14 @@
         break;
       }
 
+      case decls_block::Optimize_DECL_ATTR: {
+        unsigned kind;
+        serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
+            scratch, kind);
+        Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
+        break;
+      }
+
       case decls_block::Effects_DECL_ATTR: {
         unsigned kind;
         serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch,
@@ -3771,6 +3835,26 @@
   }
 }
 
+/// Translate from the Serialization coroutine kind enum values to the AST
+/// strongly-typed enum.
+///
+/// The former is guaranteed to be stable, but may not reflect this version of
+/// the AST.
+static Optional<swift::SILCoroutineKind>
+getActualSILCoroutineKind(uint8_t rep) {
+  switch (rep) {
+#define CASE(KIND) \
+  case (uint8_t)serialization::SILCoroutineKind::KIND: \
+    return swift::SILCoroutineKind::KIND;
+  CASE(None)
+  CASE(YieldOnce)
+  CASE(YieldMany)
+#undef CASE
+  default:
+    return None;
+  }
+}
+
 /// Translate from the serialization Ownership enumerators, which are
 /// guaranteed to be stable, to the AST ones.
 static
@@ -4248,40 +4332,23 @@
     TypeID resultID;
     uint8_t rawRep;
     bool throws = false;
-    ArrayRef<uint64_t> genericParamIDs;
+    GenericSignatureID rawGenericSig;
 
     decls_block::GenericFunctionTypeLayout::readRecord(scratch,
                                                        inputID,
                                                        resultID,
                                                        rawRep,
                                                        throws,
-                                                       genericParamIDs);
+                                                       rawGenericSig);
     auto rep = getActualFunctionTypeRepresentation(rawRep);
     if (!rep.hasValue()) {
       error();
       return nullptr;
     }
 
-    // Read the generic parameters.
-    SmallVector<GenericTypeParamType *, 4> genericParams;
-    for (auto paramID : genericParamIDs) {
-      auto param = dyn_cast_or_null<GenericTypeParamType>(
-                     getType(paramID).getPointer());
-      if (!param) {
-        error();
-        break;
-      }
-
-      genericParams.push_back(param);
-    }
-    
-    // Read the generic requirements.
-    SmallVector<Requirement, 4> requirements;
-    readGenericRequirements(requirements, DeclTypeCursor);
+    auto sig = getGenericSignature(rawGenericSig);
     auto info = GenericFunctionType::ExtInfo(*rep, throws);
-
-    auto sig = GenericSignature::get(genericParams, requirements);
-
+    
     auto inputTy = getTypeChecked(inputID);
     if (!inputTy)
       return inputTy.takeError();
@@ -4354,23 +4421,29 @@
   }
       
   case decls_block::SIL_FUNCTION_TYPE: {
+    uint8_t rawCoroutineKind;
     uint8_t rawCalleeConvention;
     uint8_t rawRepresentation;
     bool pseudogeneric = false;
     bool noescape;
     bool hasErrorResult;
     unsigned numParams;
+    unsigned numYields;
     unsigned numResults;
+    GenericSignatureID rawGenericSig;
     ArrayRef<uint64_t> variableData;
 
     decls_block::SILFunctionTypeLayout::readRecord(scratch,
+                                             rawCoroutineKind,
                                              rawCalleeConvention,
                                              rawRepresentation,
                                              pseudogeneric,
                                              noescape,
                                              hasErrorResult,
                                              numParams,
+                                             numYields,
                                              numResults,
+                                             rawGenericSig,
                                              variableData);
 
     // Process the ExtInfo.
@@ -4382,6 +4455,13 @@
     }
     SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric, noescape);
 
+    // Process the coroutine kind.
+    auto coroutineKind = getActualSILCoroutineKind(rawCoroutineKind);
+    if (!coroutineKind.hasValue()) {
+      error();
+      return nullptr;
+    }
+
     // Process the callee convention.
     auto calleeConvention = getActualParameterConvention(rawCalleeConvention);
     if (!calleeConvention.hasValue()) {
@@ -4397,6 +4477,14 @@
       return SILParameterInfo(type->getCanonicalType(), *convention);
     };
 
+    auto processYield = [&](TypeID typeID, uint64_t rawConvention)
+                                  -> Optional<SILYieldInfo> {
+      auto convention = getActualParameterConvention(rawConvention);
+      auto type = getType(typeID);
+      if (!convention || !type) return None;
+      return SILYieldInfo(type->getCanonicalType(), *convention);
+    };
+
     auto processResult = [&](TypeID typeID, uint64_t rawConvention)
                                -> Optional<SILResultInfo> {
       auto convention = getActualResultConvention(rawConvention);
@@ -4428,6 +4516,20 @@
       allParams.push_back(*param);
     }
 
+    // Process the yields.
+    SmallVector<SILYieldInfo, 8> allYields;
+    allYields.reserve(numYields);
+    for (unsigned i = 0; i != numYields; ++i) {
+      auto typeID = variableData[nextVariableDataIndex++];
+      auto rawConvention = variableData[nextVariableDataIndex++];
+      auto yield = processYield(typeID, rawConvention);
+      if (!yield) {
+        error();
+        return nullptr;
+      }
+      allYields.push_back(*yield);
+    }
+
     // Process the results.
     SmallVector<SILResultInfo, 8> allResults;
     allParams.reserve(numResults);
@@ -4454,30 +4556,19 @@
       }
     }
 
-    // Process the generic signature parameters.
-    SmallVector<GenericTypeParamType *, 8> genericParamTypes;
-    for (auto id : variableData.slice(nextVariableDataIndex)) {
-      genericParamTypes.push_back(
-                  cast<GenericTypeParamType>(getType(id)->getCanonicalType()));
-    }
-
     Optional<ProtocolConformanceRef> witnessMethodConformance;
     if (*representation == SILFunctionTypeRepresentation::WitnessMethod) {
       witnessMethodConformance = readConformance(DeclTypeCursor);
     }
 
-    // Read the generic requirements, if any.
-    SmallVector<Requirement, 4> requirements;
-    readGenericRequirements(requirements, DeclTypeCursor);
+    GenericSignature *genericSig = getGenericSignature(rawGenericSig);
 
-    GenericSignature *genericSig = nullptr;
-    if (!genericParamTypes.empty() || !requirements.empty())
-      genericSig = GenericSignature::get(genericParamTypes, requirements,
-                                         /*isKnownCanonical=*/true);
-
-    typeOrOffset = SILFunctionType::get(
-        genericSig, extInfo, calleeConvention.getValue(), allParams, allResults,
-        errorResult, ctx, witnessMethodConformance);
+    typeOrOffset = SILFunctionType::get(genericSig, extInfo,
+                                        coroutineKind.getValue(),
+                                        calleeConvention.getValue(),
+                                        allParams, allYields, allResults,
+                                        errorResult,
+                                        ctx, witnessMethodConformance);
     break;
   }
 
@@ -4891,21 +4982,7 @@
 
     // Requirement -> synthetic map.
     SmallVector<Substitution, 4> reqToSyntheticSubs;
-    if (unsigned numGenericParams = *rawIDIter++) {
-      // Generic parameters of the synthetic environment.
-      SmallVector<GenericTypeParamType *, 2> genericParams;
-      while (numGenericParams--) {
-        genericParams.push_back(
-          getType(*rawIDIter++)->castTo<GenericTypeParamType>());
-      }
-
-      // Generic requirements of the synthetic environment.
-      SmallVector<Requirement, 4> requirements;
-      readGenericRequirements(requirements, DeclTypeCursor);
-
-      // Form the generic signature for the synthetic environment.
-      syntheticSig = GenericSignature::get(genericParams, requirements);
-
+    if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
       // Create the synthetic environment.
       syntheticEnv = syntheticSig->createGenericEnvironment();
 
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index fcdcb48..d8e587f 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -407,11 +407,12 @@
   TypeID funcTyID;
   GenericEnvironmentID genericEnvID;
   unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
-      inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+      inlineStrategy, optimizationMode, effect, numSpecAttrs,
+      hasQualifiedOwnership;
   ArrayRef<uint64_t> SemanticsIDs;
-  // TODO: read fragile
   SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
-                                isThunk, isGlobal, inlineStrategy, effect,
+                                isThunk, isGlobal, inlineStrategy,
+                                optimizationMode, effect,
                                 numSpecAttrs, hasQualifiedOwnership, funcTyID,
                                 genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
@@ -475,6 +476,7 @@
         SubclassScope::NotApplicable, (Inline_t)inlineStrategy);
     fn->setGlobalInit(isGlobal == 1);
     fn->setEffectsKind((EffectsKind)effect);
+    fn->setOptimizationMode((OptimizationMode)optimizationMode);
     if (clangNodeOwner)
       fn->setClangNodeOwner(clangNodeOwner);
     for (auto ID : SemanticsIDs) {
@@ -710,7 +712,7 @@
                   (SILDeclRef::Kind)ListOfValues[NextIdx+1],
                   (swift::ResilienceExpansion)ListOfValues[NextIdx+2],
                   /*isCurried=*/false, ListOfValues[NextIdx+4] > 0);
-  if (ListOfValues[NextIdx+3] < DRef.getUncurryLevel())
+  if (ListOfValues[NextIdx+3] < DRef.getParameterListCount() - 1)
     DRef = DRef.asCurried();
   NextIdx += 5;
   return DRef;
@@ -806,6 +808,13 @@
       RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
       IsNonThrowingApply = true;
       break;
+    case SIL_BEGIN_APPLY:
+      RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst;
+      break;
+    case SIL_NON_THROWING_BEGIN_APPLY:
+      RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst;
+      IsNonThrowingApply = true;
+      break;
         
     default:
       llvm_unreachable("unexpected apply inst kind");
@@ -1067,7 +1076,8 @@
     }
     break;
   }
-  case SILInstructionKind::ApplyInst: {
+  case SILInstructionKind::ApplyInst:
+  case SILInstructionKind::BeginApplyInst: {
     // Format: attributes such as transparent, the callee's type, a value for
     // the callee and a list of values for the arguments. Each value in the list
     // is represented with 2 IDs: ValueID and ValueResultNumber.
@@ -1092,9 +1102,15 @@
       Substitutions.push_back(*sub);
     }
 
-    ResultVal = Builder.createApply(Loc, getLocalValue(ValID, FnTy),
-                                    Substitutions, Args,
-                                    IsNonThrowingApply != 0);
+    if (OpCode == SILInstructionKind::ApplyInst) {
+      ResultVal = Builder.createApply(Loc, getLocalValue(ValID, FnTy),
+                                      Substitutions, Args,
+                                      IsNonThrowingApply != 0);
+    } else {
+      ResultVal = Builder.createBeginApply(Loc, getLocalValue(ValID, FnTy),
+                                           Substitutions, Args,
+                                           IsNonThrowingApply != 0);
+    }
     break;
   }
   case SILInstructionKind::TryApplyInst: {
@@ -1417,6 +1433,8 @@
   REFCOUNTING_INSTRUCTION(UnownedRelease)
   UNARY_INSTRUCTION(IsUnique)
   UNARY_INSTRUCTION(IsUniqueOrPinned)
+  UNARY_INSTRUCTION(AbortApply)
+  UNARY_INSTRUCTION(EndApply)
 #undef UNARY_INSTRUCTION
 #undef REFCOUNTING_INSTRUCTION
 
@@ -2112,6 +2130,27 @@
     ResultVal = Builder.createUnreachable(Loc);
     break;
   }
+  case SILInstructionKind::UnwindInst: {
+    ResultVal = Builder.createUnwind(Loc);
+    break;
+  }
+  case SILInstructionKind::YieldInst: {
+    SILBasicBlock *unwindBB = getBBForReference(Fn, ListOfValues.back());
+    ListOfValues = ListOfValues.drop_back();
+    SILBasicBlock *resumeBB = getBBForReference(Fn, ListOfValues.back());
+    ListOfValues = ListOfValues.drop_back();
+
+    SmallVector<SILValue, 4> yieldedValues;
+    for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
+      auto valueTy = MF->getType(ListOfValues[I]);
+      auto valueCategory = (SILValueCategory) ListOfValues[I+1];
+      yieldedValues.push_back(
+        getLocalValue(ListOfValues[I+2], getSILType(valueTy, valueCategory)));
+    }
+
+    ResultVal = Builder.createYield(Loc, yieldedValues, resumeBB, unwindBB);
+    break;
+  }
   case SILInstructionKind::KeyPathInst: {
     unsigned nextValue = 0;
     SILType kpTy
@@ -2337,10 +2376,12 @@
   TypeID funcTyID;
   GenericEnvironmentID genericEnvID;
   unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
-    inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+    inlineStrategy, optimizationMode, effect, numSpecAttrs,
+    hasQualifiedOwnership;
   ArrayRef<uint64_t> SemanticsIDs;
   SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
-                                isThunk, isGlobal, inlineStrategy, effect,
+                                isThunk, isGlobal, inlineStrategy,
+                                optimizationMode, effect,
                                 numSpecAttrs, hasQualifiedOwnership, funcTyID,
                                 genericEnvID, clangOwnerID, SemanticsIDs);
   auto linkage = fromStableSILLinkage(rawLinkage);
@@ -2465,13 +2506,8 @@
     auto DI = FuncTable->find(*KI);
     assert(DI != FuncTable->end() && "There should never be a key without data.");
 
-    SILFunction *fn = readSILFunction(*DI, nullptr, *KI, false,
-                                      false/*errorIfEmptyBody*/);
-
-    // Update linkage for global addressors to make it pass verifier.
-    if (fn && fn->isGlobalInit() && fn->isExternalDeclaration() &&
-        fn->getLinkage() == SILLinkage::Public)
-      fn->setLinkage(SILLinkage::PublicExternal);
+    readSILFunction(*DI, nullptr, *KI, false,
+                    false/*errorIfEmptyBody*/);
   }
 }
 
@@ -2667,6 +2703,8 @@
   kind = SILCursor.readRecord(entry.ID, scratch);
 
   std::vector<SILWitnessTable::Entry> witnessEntries;
+  std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;
+
   // Another record means the end of this WitnessTable.
   while (kind != SIL_WITNESS_TABLE &&
          kind != SIL_DEFAULT_WITNESS_TABLE &&
@@ -2697,9 +2735,7 @@
       witnessEntries.push_back(SILWitnessTable::AssociatedTypeWitness{
         assoc, MF->getType(tyId)->getCanonicalType()
       });
-    } else {
-      assert(kind == SIL_WITNESS_METHOD_ENTRY &&
-             "Content of WitnessTable should be in SIL_WITNESS_METHOD_ENTRY.");
+    } else if (kind == SIL_WITNESS_METHOD_ENTRY) {
       ArrayRef<uint64_t> ListOfValues;
       DeclID NameID;
       WitnessMethodEntryLayout::readRecord(scratch, NameID, ListOfValues);
@@ -2713,6 +2749,16 @@
           getSILDeclRef(MF, ListOfValues, NextValueIndex), Func
         });
       }
+    } else {
+      assert(kind == SIL_WITNESS_CONDITIONAL_CONFORMANCE &&
+             "Content of WitnessTable should be in "
+             "SIL_WITNESS_CONDITIONAL_CONFORMANCE.");
+      TypeID assocId;
+      WitnessConditionalConformanceLayout::readRecord(scratch, assocId);
+      CanType type = MF->getType(assocId)->getCanonicalType();
+      auto conformance = MF->readConformance(SILCursor);
+      conditionalConformances.push_back(
+          SILWitnessTable::ConditionalConformance{type, conformance});
     }
 
     // Fetch the next record.
@@ -2724,7 +2770,7 @@
     kind = SILCursor.readRecord(entry.ID, scratch);
   }
 
-  wT->convertToDefinition(witnessEntries,
+  wT->convertToDefinition(witnessEntries, conditionalConformances,
                           Serialized ? IsSerialized : IsNotSerialized);
   wTableOrOffset.set(wT, /*fully deserialized*/ true);
   if (Callback)
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index 94c42c2..a9b83c7 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -16,6 +16,7 @@
 #include "swift/Subsystems.h"
 #include "swift/AST/ASTContext.h"
 #include "swift/AST/ASTMangler.h"
+#include "swift/AST/GenericSignature.h"
 #include "swift/AST/ModuleLoader.h"
 #include "swift/AST/NameLookup.h"
 #include "swift/AST/USRGeneration.h"
@@ -842,6 +843,10 @@
         assert(blobData.empty());
         LocalDeclContexts.assign(scratch.begin(), scratch.end());
         break;
+      case index_block::GENERIC_SIGNATURE_OFFSETS:
+        assert(blobData.empty());
+        GenericSignatures.assign(scratch.begin(), scratch.end());
+        break;
       case index_block::GENERIC_ENVIRONMENT_OFFSETS:
         assert(blobData.empty());
         GenericEnvironments.assign(scratch.begin(), scratch.end());
@@ -2170,6 +2175,17 @@
   return File.Bits.HasEntryPoint;
 }
 
+bool SerializedASTFile::getAllGenericSignatures(
+                       SmallVectorImpl<GenericSignature*> &genericSignatures) {
+  genericSignatures.clear();
+  for (unsigned index : indices(File.GenericSignatures)) {
+    if (auto genericSig = File.getGenericSignature(index + 1))
+      genericSignatures.push_back(genericSig);
+  }
+
+  return true;
+}
+
 ClassDecl *SerializedASTFile::getMainClass() const {
   assert(hasEntryPoint());
   return cast_or_null<ClassDecl>(File.getDecl(File.Bits.EntryPointDeclID));
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 827a2a3..55267a5 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -159,6 +159,7 @@
     SIL_WITNESS_BASE_ENTRY,
     SIL_WITNESS_ASSOC_PROTOCOL,
     SIL_WITNESS_ASSOC_ENTRY,
+    SIL_WITNESS_CONDITIONAL_CONFORMANCE,
     SIL_DEFAULT_WITNESS_TABLE,
     SIL_DEFAULT_WITNESS_TABLE_ENTRY,
     SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY,
@@ -234,6 +235,12 @@
     TypeIDField
   >;
 
+  using WitnessConditionalConformanceLayout = BCRecordLayout<
+    SIL_WITNESS_CONDITIONAL_CONFORMANCE,
+    TypeIDField // ID of associated type
+    // Trailed by the conformance itself if appropriate.
+  >;
+
   using DefaultWitnessTableLayout = BCRecordLayout<
     SIL_DEFAULT_WITNESS_TABLE,
     DeclIDField,  // ID of ProtocolDecl
@@ -268,6 +275,7 @@
                      BCFixed<2>,  // thunk/reabstraction_thunk
                      BCFixed<1>,  // global_init
                      BCFixed<2>,  // inlineStrategy
+                     BCFixed<2>,  // optimizationMode
                      BCFixed<2>,  // side effect info.
                      BCVBR<8>,    // number of specialize attributes
                      BCFixed<1>,  // has qualified ownership
@@ -355,7 +363,9 @@
     SIL_PARTIAL_APPLY,
     SIL_BUILTIN,
     SIL_TRY_APPLY,
-    SIL_NON_THROWING_APPLY
+    SIL_NON_THROWING_APPLY,
+    SIL_BEGIN_APPLY,
+    SIL_NON_THROWING_BEGIN_APPLY
   };
   
   using SILInstApplyLayout = BCRecordLayout<
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 524bc75..333ab8f 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -531,6 +531,19 @@
   return id;
 }
 
+GenericSignatureID Serializer::addGenericSignatureRef(
+                                                const GenericSignature *env) {
+  if (!env) return 0;
+
+  auto &id = GenericSignatureIDs[env];
+  if (id != 0)
+    return id;
+
+  id = ++LastGenericSignatureID;
+  GenericSignaturesToWrite.push(env);
+  return id;
+}
+
 GenericEnvironmentID Serializer::addGenericEnvironmentRef(
                                                 const GenericEnvironment *env) {
   if (!env) return 0;
@@ -759,10 +772,10 @@
   BLOCK_RECORD(index_block, OBJC_METHODS);
   BLOCK_RECORD(index_block, ENTRY_POINT);
   BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS);
+  BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS);
   BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
   BLOCK_RECORD(index_block, DECL_CONTEXT_OFFSETS);
   BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS);
-  BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
   BLOCK_RECORD(index_block, NORMAL_CONFORMANCE_OFFSETS);
   BLOCK_RECORD(index_block, SIL_LAYOUT_OFFSETS);
   BLOCK_RECORD(index_block, PRECEDENCE_GROUPS);
@@ -794,6 +807,7 @@
   BLOCK_RECORD(sil_block, SIL_WITNESS_BASE_ENTRY);
   BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL);
   BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY);
+  BLOCK_RECORD(sil_block, SIL_WITNESS_CONDITIONAL_CONFORMANCE);
   BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE);
   BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE_ENTRY);
   BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY);
@@ -1349,6 +1363,31 @@
   return true;
 }
 
+void Serializer::writeGenericSignature(const GenericSignature *sig) {
+  using namespace decls_block;
+
+  // Record the offset of this generic environment.
+  auto id = GenericSignatureIDs[sig];
+  assert(id != 0 && "generic signature not referenced properly");
+  (void)id;
+
+  assert((id - 1) == GenericSignatureOffsets.size());
+  GenericSignatureOffsets.push_back(Out.GetCurrentBitNo());
+
+  assert(sig != nullptr);
+
+  // Record the generic parameters.
+  SmallVector<uint64_t, 4> rawParamIDs;
+  for (auto *paramTy : sig->getGenericParams()) {
+    rawParamIDs.push_back(addTypeRef(paramTy));
+  }
+
+  auto abbrCode = DeclTypeAbbrCodes[GenericSignatureLayout::Code];
+  GenericSignatureLayout::emitRecord(Out, ScratchRecord, abbrCode, rawParamIDs);
+
+  writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+}
+
 void Serializer::writeGenericEnvironment(const GenericEnvironment *env) {
   using namespace decls_block;
 
@@ -1358,10 +1397,7 @@
   (void)id;
 
   assert((id - 1) == GenericEnvironmentOffsets.size());
-  GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
-
-  if (env == nullptr)
-    return;
+  assert(env != nullptr);
 
   // Determine whether we must use SIL mode, because one of the generic
   // parameters has a declaration with module context.
@@ -1375,33 +1411,36 @@
     }
   }
 
+  // If not in SIL mode, generic environments just contain a reference to
+  // the generic signature.
+  if (!SILMode) {
+    // Record the generic signature directly.
+    auto genericSigID = addGenericSignatureRef(env->getGenericSignature());
+    GenericEnvironmentOffsets.push_back((genericSigID << 1) | 0x01);
+    return;
+  }
+
+  // Record the current bit.
+  GenericEnvironmentOffsets.push_back((Out.GetCurrentBitNo() << 1));
+
   // Record the generic parameters.
   SmallVector<uint64_t, 4> rawParamIDs;
   for (auto *paramTy : env->getGenericParams()) {
     auto *decl = paramTy->getDecl();
 
     // In SIL mode, add the name and canonicalize the parameter type.
-    if (SILMode) {
-      if (decl)
-        rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
-      else
-        rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
+    if (decl)
+      rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
+    else
+      rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
 
-      paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
-    }
-
+    paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
     rawParamIDs.push_back(addTypeRef(paramTy));
   }
 
-  if (SILMode) {
-    auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
-    SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
-                                            rawParamIDs);
-  } else {
-    auto envAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
-    GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
-                                         rawParamIDs);
-  }
+  auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
+  SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
+                                          rawParamIDs);
 
   writeGenericRequirements(env->getGenericSignature()->getRequirements(),
                            DeclTypeAbbrCodes);
@@ -1425,22 +1464,14 @@
     data.push_back(typeRef);
   }
   
-  // Save generic params.
-  if (auto sig = layout->getGenericSignature()) {
-    for (auto param : sig->getGenericParams()) {
-      data.push_back(addTypeRef(param));
-    }
-  }
-  
   unsigned abbrCode
     = DeclTypeAbbrCodes[SILLayoutLayout::Code];
 
-  SILLayoutLayout::emitRecord(Out, ScratchRecord, abbrCode,
-                              layout->getFields().size(),
-                              data);
-  // Emit requirements.
-  if (auto sig = layout->getGenericSignature())
-    writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+  SILLayoutLayout::emitRecord(
+                        Out, ScratchRecord, abbrCode,
+                        addGenericSignatureRef(layout->getGenericSignature()),
+                        layout->getFields().size(),
+                        data);
 }
 
 void Serializer::writeNormalConformance(
@@ -1477,19 +1508,14 @@
       if (auto genericEnv = witness.requiresSubstitution() 
                               ? witness.getSyntheticEnvironment()
                               : nullptr) {
+        // Generic signature.
         auto *genericSig = genericEnv->getGenericSignature();
-
-        // Generic parameters.
-        data.push_back(genericSig->getGenericParams().size());
-        for (auto gp : genericSig->getGenericParams())
-          data.push_back(addTypeRef(gp));
+        data.push_back(addGenericSignatureRef(genericSig));
 
         auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
         data.push_back(reqToSyntheticSubs.size());
-
-        // Requirements come at the end.
       } else {
-        data.push_back(/*number of generic parameters*/0);
+        data.push_back(/*null generic signature*/0);
       }
 
       data.push_back(witness.getSubstitutions().size());
@@ -1531,12 +1557,6 @@
    if (auto genericEnv = witness.requiresSubstitution() 
                            ? witness.getSyntheticEnvironment()
                            : nullptr) {
-     auto *genericSig = genericEnv->getGenericSignature();
-
-     // Write the generic requirements of the synthetic environment.
-     writeGenericRequirements(genericSig->getRequirements(),
-                              DeclTypeAbbrCodes);
-
      // Write requirement-to-synthetic substitutions.
      writeSubstitutions(witness.getRequirementToSyntheticSubs(),
                         DeclTypeAbbrCodes,
@@ -1866,21 +1886,13 @@
     writeCrossReference(baseTy->getAnyNominal(), pathLen + 1);
 
     abbrCode = DeclTypeAbbrCodes[XRefExtensionPathPieceLayout::Code];
-    SmallVector<TypeID, 4> genericParams;
     CanGenericSignature genericSig(nullptr);
     if (ext->isConstrainedExtension()) {
       genericSig = ext->getGenericSignature()->getCanonicalSignature();
-      for (auto param : genericSig->getGenericParams())
-        genericParams.push_back(addTypeRef(param));
     }
     XRefExtensionPathPieceLayout::emitRecord(
         Out, ScratchRecord, abbrCode, addModuleRef(DC->getParentModule()),
-        genericParams);
-
-    if (genericSig) {
-      writeGenericRequirements(genericSig->getRequirements(),
-                               DeclTypeAbbrCodes);
-    }
+        addGenericSignatureRef(genericSig));
     break;
   }
 
@@ -2224,6 +2236,14 @@
     return;
   }
 
+  case DAK_Optimize: {
+    auto *theAttr = cast<OptimizeAttr>(DA);
+    auto abbrCode = DeclTypeAbbrCodes[OptimizeDeclAttrLayout::Code];
+    OptimizeDeclAttrLayout::emitRecord(Out, ScratchRecord, abbrCode,
+                                       (unsigned)theAttr->getMode());
+    return;
+  }
+
   case DAK_Effects: {
     auto *theAttr = cast<EffectsAttr>(DA);
     auto abbrCode = DeclTypeAbbrCodes[EffectsDeclAttrLayout::Code];
@@ -3354,6 +3374,18 @@
   llvm_unreachable("bad calling convention");
 }
 
+/// Translate from the AST coroutine-kind enum to the Serialization enum
+/// values, which are guaranteed to be stable.
+static uint8_t getRawStableSILCoroutineKind(
+                                    swift::SILCoroutineKind kind) {
+  switch (kind) {
+  SIMPLE_CASE(SILCoroutineKind, None)
+  SIMPLE_CASE(SILCoroutineKind, YieldOnce)
+  SIMPLE_CASE(SILCoroutineKind, YieldMany)
+  }
+  llvm_unreachable("bad kind");
+}
+
 /// Translate from the AST ownership enum to the Serialization enum
 /// values, which are guaranteed to be stable.
 static uint8_t getRawStableOwnership(swift::Ownership ownership) {
@@ -3398,12 +3430,11 @@
 #undef SIMPLE_CASE
 
 /// Find the typealias given a builtin type.
-static TypeAliasDecl *findTypeAliasForBuiltin(ASTContext &Ctx,
-                                              BuiltinType *Bt) {
+static TypeAliasDecl *findTypeAliasForBuiltin(ASTContext &Ctx, Type T) {
   /// Get the type name by chopping off "Builtin.".
   llvm::SmallString<32> FullName;
   llvm::raw_svector_ostream OS(FullName);
-  Bt->print(OS);
+  T->print(OS);
   assert(FullName.startswith("Builtin."));
   StringRef TypeName = FullName.substr(8);
 
@@ -3439,9 +3470,10 @@
   case TypeKind::BuiltinBridgeObject:
   case TypeKind::BuiltinUnknownObject:
   case TypeKind::BuiltinUnsafeValueBuffer:
-  case TypeKind::BuiltinVector: {
+  case TypeKind::BuiltinVector:
+  case TypeKind::SILToken: {
     TypeAliasDecl *typeAlias =
-      findTypeAliasForBuiltin(M->getASTContext(), ty->castTo<BuiltinType>());
+      findTypeAliasForBuiltin(M->getASTContext(), ty);
 
     unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
     NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -3616,19 +3648,12 @@
   case TypeKind::GenericFunction: {
     auto fnTy = cast<GenericFunctionType>(ty.getPointer());
     unsigned abbrCode = DeclTypeAbbrCodes[GenericFunctionTypeLayout::Code];
-    SmallVector<TypeID, 4> genericParams;
-    for (auto param : fnTy->getGenericParams())
-      genericParams.push_back(addTypeRef(param));
     GenericFunctionTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
             addTypeRef(fnTy->getInput()),
             addTypeRef(fnTy->getResult()),
             getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
             fnTy->throws(),
-            genericParams);
-
-    // Write requirements.
-    writeGenericRequirements(fnTy->getRequirements(),
-                             DeclTypeAbbrCodes);
+            addGenericSignatureRef(fnTy->getGenericSignature()));
     break;
   }
       
@@ -3674,6 +3699,11 @@
       unsigned conv = getRawStableParameterConvention(param.getConvention());
       variableData.push_back(TypeID(conv));
     }
+    for (auto yield : fnTy->getYields()) {
+      variableData.push_back(addTypeRef(yield.getType()));
+      unsigned conv = getRawStableParameterConvention(yield.getConvention());
+      variableData.push_back(TypeID(conv));
+    }
     for (auto result : fnTy->getResults()) {
       variableData.push_back(addTypeRef(result.getType()));
       unsigned conv = getRawStableResultConvention(result.getConvention());
@@ -3687,27 +3717,25 @@
     }
 
     auto sig = fnTy->getGenericSignature();
-    if (sig) {
-      for (auto param : sig->getGenericParams())
-        variableData.push_back(addTypeRef(param));
-    }
+
+    auto stableCoroutineKind = 
+      getRawStableSILCoroutineKind(fnTy->getCoroutineKind());
 
     auto stableCalleeConvention =
       getRawStableParameterConvention(fnTy->getCalleeConvention());
 
     unsigned abbrCode = DeclTypeAbbrCodes[SILFunctionTypeLayout::Code];
     SILFunctionTypeLayout::emitRecord(
-        Out, ScratchRecord, abbrCode, stableCalleeConvention,
+        Out, ScratchRecord, abbrCode,
+        stableCoroutineKind, stableCalleeConvention,
         stableRepresentation, fnTy->isPseudogeneric(), fnTy->isNoEscape(),
         fnTy->hasErrorResult(), fnTy->getParameters().size(),
-        fnTy->getNumResults(), variableData);
+        fnTy->getNumYields(), fnTy->getNumResults(),
+        addGenericSignatureRef(sig), variableData);
 
     if (auto conformance = fnTy->getWitnessMethodConformanceOrNone())
       writeConformance(*conformance, DeclTypeAbbrCodes);
 
-    if (sig)
-      writeGenericRequirements(sig->getRequirements(),
-                               DeclTypeAbbrCodes);
     break;
   }
       
@@ -3891,7 +3919,7 @@
   registerDeclTypeAbbr<GenericParamLayout>();
   registerDeclTypeAbbr<GenericRequirementLayout>();
   registerDeclTypeAbbr<LayoutRequirementLayout>();
-  registerDeclTypeAbbr<GenericEnvironmentLayout>();
+  registerDeclTypeAbbr<GenericSignatureLayout>();
   registerDeclTypeAbbr<SILGenericEnvironmentLayout>();
 
   registerDeclTypeAbbr<ForeignErrorConventionLayout>();
@@ -3951,6 +3979,12 @@
       writeDeclContext(next);
     }
 
+    while (!GenericSignaturesToWrite.empty()) {
+      auto next = GenericSignaturesToWrite.front();
+      GenericSignaturesToWrite.pop();
+      writeGenericSignature(next);
+    }
+
     while (!GenericEnvironmentsToWrite.empty()) {
       auto next = GenericEnvironmentsToWrite.front();
       GenericEnvironmentsToWrite.pop();
@@ -3972,6 +4006,7 @@
            !LocalDeclContextsToWrite.empty() ||
            !DeclContextsToWrite.empty() ||
            !SILLayoutsToWrite.empty() ||
+           !GenericSignaturesToWrite.empty() ||
            !GenericEnvironmentsToWrite.empty() ||
            !NormalConformancesToWrite.empty());
 }
@@ -4769,6 +4804,7 @@
     writeOffsets(Offsets, IdentifierOffsets);
     writeOffsets(Offsets, DeclContextOffsets);
     writeOffsets(Offsets, LocalDeclContextOffsets);
+    writeOffsets(Offsets, GenericSignatureOffsets);
     writeOffsets(Offsets, GenericEnvironmentOffsets);
     writeOffsets(Offsets, NormalConformanceOffsets);
     writeOffsets(Offsets, SILLayoutOffsets);
diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h
index 59a3eba..340f88a 100644
--- a/lib/Serialization/Serialization.h
+++ b/lib/Serialization/Serialization.h
@@ -100,6 +100,10 @@
   /// A map from local DeclContexts to their serialized IDs.
   llvm::DenseMap<const DeclContext*, DeclContextID> LocalDeclContextIDs;
 
+  /// A map from generic signatures to their serialized IDs.
+  llvm::DenseMap<const GenericSignature *, GenericSignatureID>
+    GenericSignatureIDs;
+
   /// A map from generic environments to their serialized IDs.
   llvm::DenseMap<const GenericEnvironment *, GenericEnvironmentID>
     GenericEnvironmentIDs;
@@ -167,6 +171,9 @@
   /// Local DeclContexts that need to be serialized.
   std::queue<const DeclContext*> LocalDeclContextsToWrite;
 
+  /// Generic signatures that need to be serialized.
+  std::queue<const GenericSignature *> GenericSignaturesToWrite;
+
   /// Generic environments that need to be serialized.
   std::queue<const GenericEnvironment*> GenericEnvironmentsToWrite;
 
@@ -202,6 +209,10 @@
   /// IdentifierID.
   std::vector<CharOffset> IdentifierOffsets;
 
+  /// The offset of each GenericSignature in the bitstream, indexed by
+  /// GenericSignatureID.
+  std::vector<BitOffset> GenericSignatureOffsets;
+
   /// The offset of each GenericEnvironment in the bitstream, indexed by
   /// GenericEnvironmentID.
   std::vector<BitOffset> GenericEnvironmentOffsets;
@@ -242,6 +253,10 @@
   uint32_t /*IdentifierID*/ LastIdentifierID =
       serialization::NUM_SPECIAL_IDS - 1;
 
+  /// The last assigned GenericSignatureID for generic signature from this
+  /// module.
+  uint32_t /*GenericSignatureID*/ LastGenericSignatureID = 0;
+
   /// The last assigned GenericEnvironmentID for generic environments from this
   /// module.
   uint32_t /*GenericEnvironmentID*/ LastGenericEnvironmentID = 0;
@@ -261,6 +276,8 @@
       return index_block::DECL_CONTEXT_OFFSETS;
     if (&values == &LocalDeclContextOffsets)
       return index_block::LOCAL_DECL_CONTEXT_OFFSETS;
+    if (&values == &GenericSignatureOffsets)
+      return index_block::GENERIC_SIGNATURE_OFFSETS;
     if (&values == &GenericEnvironmentOffsets)
       return index_block::GENERIC_ENVIRONMENT_OFFSETS;
     if (&values == &NormalConformanceOffsets)
@@ -354,6 +371,9 @@
   /// Writes the given type.
   void writeType(Type ty);
 
+  /// Writes a generic signature.
+  void writeGenericSignature(const GenericSignature *sig);
+
   /// Writes a generic environment.
   void writeGenericEnvironment(const GenericEnvironment *env);
 
@@ -436,6 +456,11 @@
   /// The DeclContext will be scheduled for serialization if necessary.
   DeclContextID addLocalDeclContextRef(const DeclContext *DC);
 
+  /// Records the use of the given generic signature.
+  ///
+  /// The GenericSignature will be scheduled for serialization if necessary.
+  GenericSignatureID addGenericSignatureRef(const GenericSignature *sig);
+
   /// Records the use of the given generic environment.
   ///
   /// The GenericEnvironment will be scheduled for serialization if necessary.
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 237f38f..3ecaf0e 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -389,7 +389,8 @@
       Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage),
       (unsigned)F.isTransparent(), (unsigned)F.isSerialized(),
       (unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
-      (unsigned)F.getInlineStrategy(), (unsigned)F.getEffectsKind(),
+      (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
+      (unsigned)F.getEffectsKind(),
       (unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
       genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
@@ -482,7 +483,7 @@
   ListOfValues.push_back(S.addDeclRef(Ref.getDecl()));
   ListOfValues.push_back((unsigned)Ref.kind);
   ListOfValues.push_back((unsigned)Ref.getResilienceExpansion());
-  ListOfValues.push_back(Ref.getUncurryLevel());
+  ListOfValues.push_back(Ref.getParameterListCount() - 1);
   ListOfValues.push_back(Ref.isForeign);
 }
 
@@ -582,6 +583,7 @@
     // TODO: decide if we want to serialize those instructions.
     return;
       
+  case SILInstructionKind::UnwindInst:
   case SILInstructionKind::UnreachableInst: {
     unsigned abbrCode = SILAbbrCodes[SILInstNoOperandLayout::Code];
     SILInstNoOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -826,6 +828,28 @@
     S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
     break;
   }
+  case SILInstructionKind::BeginApplyInst: {
+    // Format: attributes such as transparent and number of substitutions,
+    // the callee's substituted and unsubstituted types, a value for
+    // the callee and a list of values for the arguments. Each value in the list
+    // is represented with 2 IDs: ValueID and ValueResultNumber. The record
+    // is followed by the substitution list.
+    const BeginApplyInst *AI = cast<BeginApplyInst>(&SI);
+    SmallVector<ValueID, 4> Args;
+    for (auto Arg: AI->getArguments()) {
+      Args.push_back(addValueRef(Arg));
+    }
+    SILInstApplyLayout::emitRecord(Out, ScratchRecord,
+        SILAbbrCodes[SILInstApplyLayout::Code],
+        AI->isNonThrowing() ? SIL_NON_THROWING_BEGIN_APPLY : SIL_BEGIN_APPLY,
+        AI->getSubstitutions().size(),
+        S.addTypeRef(AI->getCallee()->getType().getSwiftRValueType()),
+        S.addTypeRef(AI->getSubstCalleeType()),
+        addValueRef(AI->getCallee()),
+        Args);
+    S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
+    break;
+  }
   case SILInstructionKind::TryApplyInst: {
     // Format: attributes such as transparent and number of substitutions,
     // the callee's substituted and unsubstituted types, a value for
@@ -1100,6 +1124,8 @@
   case SILInstructionKind::UnownedReleaseInst:
   case SILInstructionKind::IsUniqueInst:
   case SILInstructionKind::IsUniqueOrPinnedInst:
+  case SILInstructionKind::AbortApplyInst:
+  case SILInstructionKind::EndApplyInst:
   case SILInstructionKind::ReturnInst:
   case SILInstructionKind::UncheckedOwnershipConversionInst:
   case SILInstructionKind::ThrowInst: {
@@ -1124,6 +1150,21 @@
     writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
     break;
   }
+  case SILInstructionKind::YieldInst: {
+    auto YI = cast<YieldInst>(&SI);
+    SmallVector<ValueID, 4> args;
+    for (auto arg: YI->getYieldedValues()) {
+      args.push_back(S.addTypeRef(arg->getType().getSwiftRValueType()));
+      args.push_back((unsigned)arg->getType().getCategory());
+      args.push_back(addValueRef(arg));
+    }
+    args.push_back(BasicBlockMap[YI->getResumeBB()]);
+    args.push_back(BasicBlockMap[YI->getUnwindBB()]);
+    SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
+        SILAbbrCodes[SILOneTypeValuesLayout::Code],
+        (unsigned)YI->getKind(), 0, 0, args);
+    break;
+  }
   case SILInstructionKind::FunctionRefInst: {
     // Use SILOneOperandLayout to specify the function type and the function
     // name (IdentifierID).
@@ -2168,6 +2209,16 @@
         witnessID,
         ListOfValues);
   }
+
+  for (auto conditional : wt.getConditionalConformances()) {
+    WitnessConditionalConformanceLayout::emitRecord(
+        Out, ScratchRecord,
+        SILAbbrCodes[WitnessConditionalConformanceLayout::Code],
+        S.addTypeRef(conditional.Requirement));
+
+    S.writeConformance(conditional.Conformance, SILAbbrCodes);
+    continue;
+  }
 }
 
 void SILSerializer::
@@ -2257,6 +2308,7 @@
   registerSILAbbr<WitnessBaseEntryLayout>();
   registerSILAbbr<WitnessAssocProtocolLayout>();
   registerSILAbbr<WitnessAssocEntryLayout>();
+  registerSILAbbr<WitnessConditionalConformanceLayout>();
   registerSILAbbr<DefaultWitnessTableLayout>();
   registerSILAbbr<DefaultWitnessTableEntryLayout>();
   registerSILAbbr<DefaultWitnessTableNoEntryLayout>();
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 1c80bee..4acef87 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -23,6 +23,8 @@
 
 namespace {
 static bool isTrivialSyntaxKind(SyntaxKind Kind) {
+  if (isUnknownKind(Kind))
+    return true;
   if (isCollectionKind(Kind))
     return true;
   switch(Kind) {
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index b534351..6a954e6 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -57,6 +57,32 @@
   return make<UnknownSyntax>(Raw);
 }
 
+Syntax SyntaxFactory::makeBlankCollectionSyntax(SyntaxKind Kind) {
+  switch(Kind) {
+% for node in SYNTAX_NODES:
+%   if node.is_syntax_collection():
+  case SyntaxKind::${node.syntax_kind}: return makeBlank${node.syntax_kind}();
+%   end
+% end
+  default: break;
+  }
+  llvm_unreachable("not collection kind.");
+}
+
+std::pair<unsigned, unsigned>
+SyntaxFactory::countChildren(SyntaxKind Kind){
+  switch(Kind) {
+% for node in SYNTAX_NODES:
+  case SyntaxKind::${node.syntax_kind}:
+% child_count = len(node.children)
+% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children)
+    return {${non_optional_child_count}, ${child_count}};
+% end
+  default:
+  llvm_unreachable("bad syntax kind.");
+  }
+}
+
 Optional<Syntax>
 SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) {
   switch(Kind) {
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index eb8e495..af28b2c 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -56,19 +56,34 @@
   assert(StartLoc.isValid() == EndLoc.isValid());
   return SourceRange(StartLoc, EndLoc);
 }
+
+static RawSyntaxInfo createSyntaxAs(ArrayRef<RawSyntaxInfo> Parts,
+                                    SyntaxKind Kind) {
+  llvm::SmallVector<Syntax, 8> Scratch;
+  auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+
+  // Try to create the node of the given syntax.
+  Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
+  if (!Result) {
+
+    // If unable to create, we should create an unknown node.
+    Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
+                                     SyntaxParts));
+  }
+  return { getNodesRange(Parts), Result->getRaw() };
+}
 } // End of anonymous namespace
 
 struct SyntaxParsingContext::ContextInfo {
   bool Enabled;
 private:
   SourceLoc ContextStartLoc;
-  SourceLoc ContextEndLoc;
   std::vector<RawSyntaxInfo> PendingSyntax;
 
   // All tokens after the start of this context.
   ArrayRef<RawSyntaxInfo> Tokens;
 
-  ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) {
+  ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) const {
     for (auto It = Tokens.begin(); It != Tokens.end(); It ++) {
       assert(It->getStartLoc() == It->getEndLoc());
       if (It->getStartLoc() == Loc)
@@ -96,15 +111,19 @@
   }
 
   // Squash N syntax nodex from the back of the pending list into one.
-  void createFromBack(SyntaxKind Kind, unsigned N = 0);
-  std::vector<RawSyntaxInfo> collectAllSyntax();
+  void createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+                               unsigned N);
+  void createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse);
+  std::vector<RawSyntaxInfo> collectAllSyntax(SourceLoc EndLoc);
   ArrayRef<RawSyntaxInfo> allTokens() const { return Tokens; }
-  ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; };
+  ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; }
+  SourceLoc getContextStartLoc() const { return ContextStartLoc; }
 
   void addPendingSyntax(RawSyntaxInfo Info) {
     assert(Info.isImplicit() || PendingSyntax.empty() ||
            PendingSyntax.back().getStartLoc().getOpaquePointerValue() <
              Info.getStartLoc().getOpaquePointerValue());
+    assert(!Info.RawNode->isToken() && "Pending syntax should not have tokens");
     PendingSyntax.push_back(Info);
   }
 
@@ -114,42 +133,65 @@
     Tokens = Tokens.slice(findTokenAt(Loc) - Tokens.begin());
   }
 
-  void setContextEnd(SourceLoc Loc) {
-    assert(ContextEndLoc.isInvalid());
-    ContextEndLoc = Loc;
-    Tokens = Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
-  }
-
-  void promoteTokenAt(SourceLoc Loc) {
-    PendingSyntax.push_back(*findTokenAt(Loc));
+  ArrayRef<RawSyntaxInfo> dropTokenAt(SourceLoc Loc) const {
+    return Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
   }
 
   // Check if the pending syntax is a token syntax in the given kind.
-  bool checkTokenFromBack(tok Kind, unsigned OffsetFromBack = 0) {
-    if (PendingSyntax.size() - 1 < OffsetFromBack)
+  bool checkTokenFromBack(tok Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+                          unsigned OffsetFromBack = 0) {
+    if (UsedTokens.size() - 1 < OffsetFromBack)
       return false;
-    auto Back = PendingSyntax[PendingSyntax.size() - 1 - OffsetFromBack].
+    auto Back = UsedTokens[UsedTokens.size() - 1 - OffsetFromBack].
       makeSyntax<Syntax>().getAs<TokenSyntax>();
     return Back.hasValue() && Back->getTokenKind() == Kind;
   }
 };
 
+static void addNodeToResults(std::vector<RawSyntaxInfo> &Results,
+                             std::vector<RawSyntaxInfo> &ImplicitNodes,
+                             RawSyntaxInfo Info) {
+  // Add implicit nodes before adding the explicit nodes they attach to.
+  assert(!Info.isImplicit());
+  auto StartSize = Results.size();
+
+  // Find all implicit nodes where the attach-to location is the start position
+  // of this non-implicit nodes.
+  Results.insert(Results.end(),
+                 std::find_if(ImplicitNodes.begin(), ImplicitNodes.end(),
+                   [&](const RawSyntaxInfo &Imp) {
+                     return Imp.BeforeLoc == Info.getStartLoc();
+                   }),
+                 ImplicitNodes.end());
+
+  // If any implicit nodes are inserted to results, we should clear the buffer
+  // to avoid re-inserting them.
+  if (StartSize != Results.size()) {
+    ImplicitNodes.clear();
+  }
+
+  // Add the non-implicit node.
+  Results.emplace_back(Info);
+}
+
 std::vector<RawSyntaxInfo>
-SyntaxParsingContext::ContextInfo::collectAllSyntax() {
+SyntaxParsingContext::ContextInfo::collectAllSyntax(SourceLoc EndLoc) {
   std::vector<RawSyntaxInfo> Results;
+  std::vector<RawSyntaxInfo> ImplicitNodes;
   auto CurSyntax = PendingSyntax.begin();
-  for (auto It = Tokens.begin(); It != Tokens.end();) {
+  for (auto It = Tokens.begin(); It->getStartLoc() != EndLoc;) {
     auto Tok = *It;
     if (CurSyntax == PendingSyntax.end()) {
       // If no remaining syntax nodes, add the token.
-      Results.emplace_back(Tok);
+      addNodeToResults(Results, ImplicitNodes, Tok);
       It ++;
     } else if (CurSyntax->isImplicit()) {
+      ImplicitNodes.emplace_back(*CurSyntax);
       // Skip implicit syntax node.
       CurSyntax ++;
     } else if (CurSyntax->getStartLoc() == Tok.getStartLoc()) {
       // Prefer syntax nodes to tokens.
-      Results.emplace_back(*CurSyntax);
+      addNodeToResults(Results, ImplicitNodes, *CurSyntax);
       while(It->getEndLoc() != CurSyntax->getEndLoc()) It++;
       assert(It < Tokens.end() && It->getEndLoc() == CurSyntax->getEndLoc());
       It ++;
@@ -159,7 +201,7 @@
       // started.
       assert(Tok.getStartLoc().getOpaquePointerValue() <
              CurSyntax->getStartLoc().getOpaquePointerValue());
-      Results.push_back(Tok);
+      addNodeToResults(Results, ImplicitNodes, Tok);
       It ++;
     }
   }
@@ -170,40 +212,42 @@
   return Results;
 }
 
-void
-SyntaxParsingContext::ContextInfo::createFromBack(SyntaxKind Kind, unsigned N) {
-  auto Size = PendingSyntax.size();
-  if (!N)
-    N = Size;
-  assert(Size >= N);
-  auto Parts = llvm::makeArrayRef(PendingSyntax).slice(Size - N);
-  llvm::SmallVector<Syntax, 8> Scratch;
-  auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+void SyntaxParsingContext::ContextInfo::
+createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse,
+                        unsigned N) {
+  auto Size = NodesToUse.size();
+  assert(N && Size >= N);
+  auto Parts = llvm::makeArrayRef(NodesToUse).slice(Size - N);
 
-  // Try to create the node of the given syntax.
-  Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
-  if (!Result) {
+  // Count the parts from the pending syntax list.
+  unsigned UsedPending = std::accumulate(Parts.begin(), Parts.end(), 0,
+    [](unsigned Count, RawSyntaxInfo Info) {
+      return Count += Info.RawNode->isToken() ? 0 : 1;
+    });
 
-    // If unable to create, we should create an unknown node.
-    Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
-                                     SyntaxParts));
-  }
-  RawSyntaxInfo NewSyntaxNode(getNodesRange(Parts), Result->getRaw());
-
-  // Remove the building bricks and re-append the result.
-  for (unsigned I = 0; I < N; I ++)
+  // Remove all pending syntax ndoes that we used to create the new node.
+  for (unsigned I = 0; I < UsedPending; I ++)
     PendingSyntax.pop_back();
-  addPendingSyntax(NewSyntaxNode);
-  assert(Size - N + 1 == PendingSyntax.size());
+
+  // Add result to the pending syntax list.
+  addPendingSyntax(createSyntaxAs(Parts, Kind));
+}
+
+void SyntaxParsingContext::ContextInfo::
+createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse) {
+  auto Result = createSyntaxAs(NodesToUse, Kind);
+  PendingSyntax.clear();
+  addPendingSyntax(Result);
 }
 
 SyntaxParsingContext::
 SyntaxParsingContext(SourceFile &SF, unsigned BufferID, Token &Tok):
-  ContextData(*new ContextInfo(SF, BufferID)), Tok(Tok) {}
+  ContextData(*new ContextInfo(SF, BufferID)),
+    Tok(Tok) {}
 
 SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext &Another):
   ContextData(*new ContextInfo(Another.ContextData.allTokens(),
-                               Another.ContextData.Enabled)), Tok(Another.Tok) {}
+    Another.ContextData.Enabled)), Tok(Another.Tok) {}
 
 SyntaxParsingContext::~SyntaxParsingContext() { delete &ContextData; }
 
@@ -241,40 +285,58 @@
 
 SyntaxParsingContextChild::
 SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
-      Optional<SyntaxContextKind> Kind, Optional<SyntaxKind> KnownSyntax):
+      Optional<SyntaxContextKind> ContextKind, Optional<SyntaxKind> KnownSyntax):
     SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
-    ContextHolder(ContextHolder), Kind(Kind), KnownSyntax(KnownSyntax) {
-  assert(Kind.hasValue() != KnownSyntax.hasValue());
+    ContextHolder(ContextHolder), ContextKind(ContextKind),
+    KnownSyntax(KnownSyntax) {
   ContextHolder = this;
   if (ContextData.Enabled)
     ContextData.setContextStart(Tok.getLoc());
 }
 
-
-void SyntaxParsingContextChild::addTokenSyntax(SourceLoc Loc) {
-  if (ContextData.Enabled)
-    ContextData.promoteTokenAt(Loc);
+void SyntaxParsingContextChild::setSyntaxKind(SyntaxKind SKind) {
+  assert(!KnownSyntax.hasValue() && "reset");
+  KnownSyntax = SKind;
+  ContextKind = None;
 }
 
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind) {
+void SyntaxParsingContextChild::setContextKind(SyntaxContextKind CKind) {
+  assert(!ContextKind.hasValue() && "reset");
+  ContextKind = CKind;
+  KnownSyntax = None;
+}
+
+SyntaxParsingContextChild::
+SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder, bool Disable):
+    SyntaxParsingContextChild(ContextHolder, None, None) {
+  if (Disable)
+    disable();
+}
+
+void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc EndLoc) {
+  assert(isTopOfContextStack());
   if (!ContextData.Enabled)
     return;
 
+  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
+
   // Create syntax nodes according to the given kind.
   switch (Kind) {
   case SyntaxKind::FloatLiteralExpr:
   case SyntaxKind::IntegerLiteralExpr: {
     // Integer may include the signs before the digits, so check if the sign
     // exists and create.
-    ContextData.createFromBack(Kind, ContextData.
-      checkTokenFromBack(tok::oper_prefix, 1) ? 2 : 1);
+    ContextData.createPartiallyFromBack(Kind, AllNodes, ContextData.
+      checkTokenFromBack(tok::oper_prefix, AllNodes, 1) ? 2 : 1);
     break;
   }
+  case SyntaxKind::TernaryExpr:
   case SyntaxKind::StringLiteralExpr: {
-    ContextData.createFromBack(Kind, 1);
+    auto Pair = SyntaxFactory::countChildren(Kind);
+    assert(Pair.first == Pair.second);
+    ContextData.createPartiallyFromBack(Kind, AllNodes, Pair.first);
     break;
   }
-
   default:
     llvm_unreachable("Unrecognized node kind.");
   }
@@ -282,17 +344,36 @@
 
 void SyntaxParsingContextChild::makeNodeWhole(SyntaxKind Kind) {
   assert(ContextData.Enabled);
+  assert(isTopOfContextStack());
+
+  auto EndLoc = Tok.getLoc();
+  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
   switch (Kind) {
+  case SyntaxKind::BooleanLiteralExpr:
+  case SyntaxKind::NilLiteralExpr:
+  case SyntaxKind::DiscardAssignmentExpr:
+  case SyntaxKind::IdentifierExpr:
+  case SyntaxKind::DictionaryExpr:
+  case SyntaxKind::ArrayExpr:
+  case SyntaxKind::DictionaryElement:
+  case SyntaxKind::ArrayElement:
+  case SyntaxKind::FunctionCallArgument:
   case SyntaxKind::CodeBlock: {
-    ContextData.createFromBack(Kind);
+    ContextData.createWhole(Kind, AllNodes);
     break;
   }
-  case SyntaxKind::StmtList: {
-    if (ContextData.getPendingSyntax().empty()) {
-      // Create an empty statement list if no statement is in the context.
-      ContextData.addPendingSyntax({SyntaxFactory::makeBlankStmtList().getRaw()});
+  case SyntaxKind::DictionaryElementList:
+  case SyntaxKind::ArrayElementList:
+  case SyntaxKind::StmtList:
+  case SyntaxKind::FunctionCallArgumentList: {
+    if (AllNodes.empty()) {
+      // Create an empty argument list if no arguments are in the context.
+      RawSyntaxInfo Empty(SyntaxFactory::
+                          makeBlankCollectionSyntax(Kind).getRaw());
+      Empty.setBeforeLoc(EndLoc);
+      ContextData.addPendingSyntax(Empty);
     } else {
-      ContextData.createFromBack(Kind);
+      ContextData.createWhole(Kind, AllNodes);
     }
     break;
   }
@@ -321,13 +402,27 @@
     assert(RawNode->isStmt());
     break;
   }
-  case SyntaxContextKind::Decl:
+  case SyntaxContextKind::Decl: {
+    if (!RawNode->isDecl()) {
+      RawNode = makeUnknownSyntax(SyntaxKind::UnknownDecl,
+                                  {make<Syntax>(RawNode)}).getRaw();
+    }
+    assert(RawNode->isDecl());
+    break;
+  }
+
   case SyntaxContextKind::Expr:
+    if (!RawNode->isExpr()) {
+      RawNode = makeUnknownSyntax(SyntaxKind::UnknownExpr,
+                                  {make<Syntax>(RawNode)}).getRaw();
+    }
+    assert(RawNode->isExpr());
     break;
   }
 }
 
-SyntaxParsingContextChild::~SyntaxParsingContextChild() {
+void SyntaxParsingContextChild::finalize() {
+  assert(isTopOfContextStack());
   SWIFT_DEFER {
     // Reset the context holder to be Parent.
     ContextHolder = Parent;
@@ -335,32 +430,29 @@
   if (!ContextData.Enabled)
     return;
 
-  // Set the end of the context.
-  ContextData.setContextEnd(Tok.getLoc());
+  assert(ContextKind.hasValue() != KnownSyntax.hasValue());
+  SourceLoc EndLoc = Tok.getLoc();
   if (KnownSyntax) {
     // If the entire context should be created to a known syntax kind, create
     // all pending syntax nodes into that node.
     makeNodeWhole(*KnownSyntax);
     assert(ContextData.getPendingSyntax().size() == 1);
-    auto AllNodes = ContextData.collectAllSyntax();
-    assert(AllNodes.size() == 1);
-    Parent->ContextData.addPendingSyntax(AllNodes.front());
+    Parent->ContextData.addPendingSyntax(ContextData.getPendingSyntax().front());
     return;
   }
-  auto AllNodes = ContextData.collectAllSyntax();
+  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
   RC<RawSyntax> FinalResult;
   if (AllNodes.empty())
     return;
 
   // Make sure we used all tokens.
-  assert(AllNodes.front().getStartLoc() == ContextData.allTokens().front().getStartLoc());
-  assert(AllNodes.back().getEndLoc() == ContextData.allTokens().back().getStartLoc());
+  assert(AllNodes.front().getStartLoc() == ContextData.getContextStartLoc());
 
   if (AllNodes.size() == 1) {
     // If we have only one syntax node remaining, we are done.
     auto Result = AllNodes.front();
     // Bridge the syntax node to the expected context kind.
-    Result.brigeWithContext(*Kind);
+    Result.brigeWithContext(*ContextKind);
     Parent->ContextData.addPendingSyntax(Result);
     return;
   }
@@ -370,7 +462,7 @@
   SourceLoc Start = AllNodes.front().getStartLoc();
   SourceLoc End = AllNodes.back().getEndLoc();
   SyntaxKind UnknownKind;
-  switch (*Kind) {
+  switch (*ContextKind) {
     case SyntaxContextKind::Expr:
       UnknownKind = SyntaxKind::UnknownExpr;
       break;
@@ -385,3 +477,8 @@
   Parent->ContextData.addPendingSyntax({SourceRange(Start, End),
     makeUnknownSyntax(UnknownKind, SyntaxNodes).getRaw()});
 }
+
+SyntaxParsingContextChild::~SyntaxParsingContextChild() {
+  if (isTopOfContextStack())
+    finalize();
+}
diff --git a/stdlib/public/Platform/Glibc.swift.gyb b/stdlib/public/Platform/Glibc.swift.gyb
index f49c8c7..4c01157 100644
--- a/stdlib/public/Platform/Glibc.swift.gyb
+++ b/stdlib/public/Platform/Glibc.swift.gyb
@@ -12,8 +12,7 @@
 
 @_exported import SwiftGlibc // Clang module
 
-public let MAP_FAILED =
-  UnsafeMutableRawPointer(bitPattern: -1)! as UnsafeMutableRawPointer!
+public let MAP_FAILED: UnsafeMutableRawPointer! = UnsafeMutableRawPointer(bitPattern: -1)
 
 //  Constants defined by <math.h>
 @available(swift, deprecated: 3.0, message: "Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.")
diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp
index 18a0d5a..c782c71 100644
--- a/stdlib/public/Reflection/TypeRef.cpp
+++ b/stdlib/public/Reflection/TypeRef.cpp
@@ -147,9 +147,6 @@
       if (flags.isShared())
         printHeader("shared");
 
-      if (flags.isEscaping())
-        printHeader("escaping");
-
       printRec(param.getType());
 
       if (!flags.isNone()) {
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index 3346d89..9ee047b 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -73,7 +73,7 @@
 extension NSApplication {
   @available(swift 4)
   public static func loadApplication() {
-    NSApplicationLoad()
+    __NSApplicationLoad()
   }
 }
 
@@ -90,7 +90,7 @@
 
 extension NSImage : _ExpressibleByImageLiteral {
   private convenience init!(failableImageLiteral name: String) {
-    self.init(named: name)
+    self.init(named: .init(name))
   }
 
   @nonobjc
@@ -100,3 +100,61 @@
 }
 
 public typealias _ImageLiteralType = NSImage
+
+// Numeric backed types
+
+@available(swift 4)
+public protocol _AppKitKitNumericRawRepresentable : RawRepresentable, Comparable
+  where RawValue: Comparable & Numeric { }
+
+extension _AppKitKitNumericRawRepresentable {
+  public static func <(lhs: Self, rhs: Self) -> Bool {
+    return lhs.rawValue < rhs.rawValue
+  }
+
+  public static func +(lhs: Self, rhs: RawValue) -> Self {
+    return Self(rawValue: lhs.rawValue + rhs)!
+  }
+
+  public static func +(lhs: RawValue, rhs: Self) -> Self {
+    return Self(rawValue: lhs + rhs.rawValue)!
+  }
+
+  public static func -(lhs: Self, rhs: RawValue) -> Self {
+    return Self(rawValue: lhs.rawValue - rhs)!
+  }
+
+  public static func -(lhs: Self, rhs: Self) -> RawValue {
+    return lhs.rawValue - rhs.rawValue
+  }
+
+  public static func +=(lhs: inout Self, rhs: RawValue) {
+    lhs = Self(rawValue: lhs.rawValue + rhs)!
+  }
+
+  public static func -=(lhs: inout Self, rhs: RawValue) {
+    lhs = Self(rawValue: lhs.rawValue - rhs)!
+  }
+}
+
+@available(swift 4)
+extension NSAppKitVersion : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSLayoutConstraint.Priority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSStackView.VisibilityPriority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSToolbarItem.VisibilityPriority : _AppKitKitNumericRawRepresentable { }
+
+@available(macOS 10.12.2, *)
+@available(swift 4)
+extension NSTouchBarItem.Priority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSWindow.Level : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSFont.Weight : _AppKitKitNumericRawRepresentable { }
diff --git a/stdlib/public/SDK/AppKit/CMakeLists.txt b/stdlib/public/SDK/AppKit/CMakeLists.txt
index 34bacd6..32dadc5 100644
--- a/stdlib/public/SDK/AppKit/CMakeLists.txt
+++ b/stdlib/public/SDK/AppKit/CMakeLists.txt
@@ -8,7 +8,7 @@
   NSGraphics.swift
   NSOpenGL.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} -swift-version 4 
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX
   SWIFT_MODULE_DEPENDS_OSX Darwin CoreData CoreGraphics CoreImage Dispatch Foundation IOKit ObjectiveC QuartzCore XPC # auto-updated
diff --git a/stdlib/public/SDK/AppKit/NSGraphics.swift b/stdlib/public/SDK/AppKit/NSGraphics.swift
index a453f47..6cc836c 100644
--- a/stdlib/public/SDK/AppKit/NSGraphics.swift
+++ b/stdlib/public/SDK/AppKit/NSGraphics.swift
@@ -21,10 +21,10 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func fill(using operation: NSCompositingOperation =
-    NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
-    precondition(NSGraphicsContext.current() != nil,
+    NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
-    NSRectFillUsingOperation(self, operation)
+    __NSRectFillUsingOperation(self, operation)
   }
     
   /// Draws a frame around the inside of this rect in the current
@@ -35,10 +35,10 @@
   @available(swift 4)
   public func frame(withWidth width: CGFloat = 1.0,
                     using operation: NSCompositingOperation =
-    NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
-    precondition(NSGraphicsContext.current() != nil,
+    NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
-    NSFrameRectWithWidthUsingOperation(self, width, operation)
+    __NSFrameRectWithWidthUsingOperation(self, width, operation)
   }
     
   /// Modifies the current graphics context clipping path by intersecting it
@@ -48,9 +48,9 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func clip() {
-    precondition(NSGraphicsContext.current() != nil,
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
-    NSRectClip(self)
+    __NSRectClip(self)
   }
 }
 
@@ -62,15 +62,15 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func fill(using operation: NSCompositingOperation =
-    NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
-    precondition(NSGraphicsContext.current() != nil,
+    NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
     let rects = Array(self)
     let count = rects.count
     guard count > 0 else { return }
     rects.withUnsafeBufferPointer { rectBufferPointer in
       guard let rectArray = rectBufferPointer.baseAddress else { return }
-      NSRectFillListUsingOperation(rectArray, count, operation)
+      __NSRectFillListUsingOperation(rectArray, count, operation)
     }
   }
     
@@ -81,14 +81,14 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func clip() {
-    precondition(NSGraphicsContext.current() != nil,
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
     let rects = Array(self)
     let count = rects.count
     guard count > 0 else { return }
     rects.withUnsafeBufferPointer { rectBufferPointer in
       guard let rectArray = rectBufferPointer.baseAddress else { return }
-      NSRectClipList(rectArray, count)
+      __NSRectClipList(rectArray, count)
     }
   }
 }
@@ -101,8 +101,8 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func fill(using operation: NSCompositingOperation =
-    NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
-    precondition(NSGraphicsContext.current() != nil,
+    NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+    precondition(NSGraphicsContext.current != nil,
                  "There must be a set current NSGraphicsContext")
     let rects = map { $0.0 }
     let colors = map { $0.1 }
@@ -112,7 +112,7 @@
       colors.withUnsafeBufferPointer { colorBufferPointer in
         guard let rectArray = rectBufferPointer.baseAddress else { return }
         guard let colorArray = colorBufferPointer.baseAddress else { return }
-        NSRectFillListWithColorsUsingOperation(
+        __NSRectFillListWithColorsUsingOperation(
             rectArray, colorArray, count, operation)
       }
     }
@@ -128,10 +128,10 @@
   /// - precondition: There must be a set current NSGraphicsContext.
   @available(swift 4)
   public func fill(using operation: NSCompositingOperation =
-    NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
+    NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
     // NSRectFillListWithGrays does not have a variant taking an operation, but
     // is added here for consistency with the other drawing operations.
-    guard let graphicsContext = NSGraphicsContext.current() else {
+    guard let graphicsContext = NSGraphicsContext.current else {
       fatalError("There must be a set current NSGraphicsContext")
     }
     let cgContext: CGContext
@@ -144,31 +144,31 @@
     cgContext.saveGState()
     forEach {
       cgContext.setFillColor(gray: $0.gray, alpha: 1.0)
-      NSRectFillUsingOperation($0.0, operation)
+      __NSRectFillUsingOperation($0.0, operation)
     }
     cgContext.restoreGState()
   }
 }
 
-extension NSWindowDepth {
+extension NSWindow.Depth {
   @available(swift 4)
   public static func bestDepth(
     colorSpaceName: NSColorSpaceName,
     bitsPerSample: Int,
     bitsPerPixel: Int,
     isPlanar: Bool
-    ) -> (NSWindowDepth, isExactMatch: Bool) {
+    ) -> (NSWindow.Depth, isExactMatch: Bool) {
     var isExactMatch: ObjCBool = false
-    let depth = NSBestDepth(
-        colorSpaceName as String,
+    let depth = __NSBestDepth(
+        colorSpaceName,
         bitsPerSample, bitsPerPixel, isPlanar, &isExactMatch)
     return (depth, isExactMatch: isExactMatch.boolValue)
   }
   @available(swift 4)
-  public static var availableDepths: [NSWindowDepth] {
+  public static var availableDepths: [NSWindow.Depth] {
     // __NSAvailableWindowDepths is NULL terminated, the length is not known up front
-    let depthsCArray = NSAvailableWindowDepths()
-    var depths: [NSWindowDepth] = []
+    let depthsCArray = __NSAvailableWindowDepths()
+    var depths: [NSWindow.Depth] = []
     var length = 0
     var depth = depthsCArray[length]
     while depth.rawValue != 0 {
@@ -194,7 +194,7 @@
     delegate.completionHandler = completionHandler
     // Note that the delegate of `__NSShowAnimationEffect` is retained for the
     // duration of the animation.
-    NSShowAnimationEffect(
+    __NSShowAnimationEffect(
         self,
         centerLocation,
         size,
@@ -207,6 +207,6 @@
 extension NSSound {
   @available(swift 4)
   public static func beep() {
-    NSBeep()
+    __NSBeep()
   }
 }
diff --git a/stdlib/public/SDK/AppKit/NSOpenGL.swift b/stdlib/public/SDK/AppKit/NSOpenGL.swift
index 100a517..02f967d 100644
--- a/stdlib/public/SDK/AppKit/NSOpenGL.swift
+++ b/stdlib/public/SDK/AppKit/NSOpenGL.swift
@@ -18,11 +18,11 @@
   public var globalValue: GLint {
     get {
       var value: GLint = 0
-      NSOpenGLGetOption(self, &value)
+      __NSOpenGLGetOption(self, &value)
       return value
     }
     set {
-      NSOpenGLSetOption(self, newValue)
+      __NSOpenGLSetOption(self, newValue)
     }
   }
 }
@@ -32,7 +32,7 @@
   public static var openGLVersion: (major: GLint, minor: GLint) {
     var major: GLint = 0
     var minor: GLint = 0
-    NSOpenGLGetVersion(&major, &minor)
+    __NSOpenGLGetVersion(&major, &minor)
     return (major: major, minor: minor)
   }
 }
diff --git a/stdlib/public/SDK/CoreGraphics/CMakeLists.txt b/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
index da36b64..09101e8 100644
--- a/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
+++ b/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
@@ -6,7 +6,7 @@
   CGFloat.swift.gyb
   Private.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation Dispatch IOKit ObjectiveC # auto-updated
   SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
diff --git a/stdlib/public/SDK/Foundation/CMakeLists.txt b/stdlib/public/SDK/Foundation/CMakeLists.txt
index 0436cf1..b6cdce9 100644
--- a/stdlib/public/SDK/Foundation/CMakeLists.txt
+++ b/stdlib/public/SDK/Foundation/CMakeLists.txt
@@ -57,7 +57,7 @@
   UUID.swift
   CheckClass.mm
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization" "-swift-version" "3"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
 
   SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch IOKit ObjectiveC # auto-updated
diff --git a/stdlib/public/SDK/Foundation/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index a0b6e88..8083b9e 100644
--- a/stdlib/public/SDK/Foundation/Data.swift
+++ b/stdlib/public/SDK/Foundation/Data.swift
@@ -198,20 +198,20 @@
         switch _backing {
         case .swift: fallthrough
         case .mutable:
-            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
         case .customMutableReference(let d):
             let len = d.length
-            return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+            return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
         case .immutable(let d):
             let data = d.mutableCopy() as! NSMutableData
             _backing = .mutable(data)
             _bytes = data.mutableBytes
-            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+            return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
         case .customReference(let d):
             let data = d.mutableCopy() as! NSMutableData
             _backing = .customMutableReference(data)
             let len = data.length
-            return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+            return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
         }
     }
 
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index 9901552..a8d5e6a 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -867,8 +867,8 @@
         }
 
         let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
-        guard let value = try decoder.unbox(topLevel, as: T.self) else {
-            throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+        guard let value = try decoder.unbox(topLevel, as: type) else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
         }
 
         return value
@@ -1236,7 +1236,7 @@
         self.decoder.codingPath.append(key)
         defer { self.decoder.codingPath.removeLast() }
 
-        guard let value = try self.decoder.unbox(entry, as: T.self) else {
+        guard let value = try self.decoder.unbox(entry, as: type) else {
             throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
         }
 
@@ -1575,7 +1575,7 @@
         self.decoder.codingPath.append(_JSONKey(index: self.currentIndex))
         defer { self.decoder.codingPath.removeLast() }
 
-        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
             throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
         }
 
@@ -1734,8 +1734,8 @@
     }
 
     public func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        try expectNonNull(T.self)
-        return try self.unbox(self.storage.topContainer, as: T.self)!
+        try expectNonNull(type)
+        return try self.unbox(self.storage.topContainer, as: type)!
     }
 }
 
@@ -2094,13 +2094,13 @@
 
     fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
         let decoded: T
-        if T.self == Date.self || T.self == NSDate.self {
+        if type == Date.self || type == NSDate.self {
             guard let date = try self.unbox(value, as: Date.self) else { return nil }
             decoded = date as! T
-        } else if T.self == Data.self || T.self == NSData.self {
+        } else if type == Data.self || type == NSData.self {
             guard let data = try self.unbox(value, as: Data.self) else { return nil }
             decoded = data as! T
-        } else if T.self == URL.self || T.self == NSURL.self {
+        } else if type == URL.self || type == NSURL.self {
             guard let urlString = try self.unbox(value, as: String.self) else {
                 return nil
             }
@@ -2111,12 +2111,12 @@
             }
 
             decoded = (url as! T)
-        } else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
+        } else if type == Decimal.self || type == NSDecimalNumber.self {
             guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
             decoded = decimal as! T
         } else {
             self.storage.push(container: value)
-            decoded = try T(from: self)
+            decoded = try type.init(from: self)
             self.storage.popContainer()
         }
 
diff --git a/stdlib/public/SDK/Foundation/PlistEncoder.swift b/stdlib/public/SDK/Foundation/PlistEncoder.swift
index 059e237..9544870 100644
--- a/stdlib/public/SDK/Foundation/PlistEncoder.swift
+++ b/stdlib/public/SDK/Foundation/PlistEncoder.swift
@@ -612,7 +612,7 @@
     /// - throws: An error if any value throws an error during decoding.
     open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
         var format: PropertyListSerialization.PropertyListFormat = .binary
-        return try decode(T.self, from: data, format: &format)
+        return try decode(type, from: data, format: &format)
     }
 
     /// Decodes a top-level value of the given type from the given property list representation.
@@ -631,7 +631,7 @@
             throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not a valid property list.", underlyingError: error))
         }
 
-        return try decode(T.self, fromTopLevel: topLevel)
+        return try decode(type, fromTopLevel: topLevel)
     }
 
     /// Decodes a top-level value of the given type from the given property list container (top-level array or dictionary).
@@ -643,8 +643,8 @@
     /// - throws: An error if any value throws an error during decoding.
     internal func decode<T : Decodable>(_ type: T.Type, fromTopLevel container: Any) throws -> T {
         let decoder = _PlistDecoder(referencing: container, options: self.options)
-        guard let value = try decoder.unbox(container, as: T.self) else {
-            throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+        guard let value = try decoder.unbox(container, as: type) else {
+            throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
         }
 
         return value
@@ -1015,7 +1015,7 @@
         self.decoder.codingPath.append(key)
         defer { self.decoder.codingPath.removeLast() }
 
-        guard let value = try self.decoder.unbox(entry, as: T.self) else {
+        guard let value = try self.decoder.unbox(entry, as: type) else {
             throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
         }
 
@@ -1354,7 +1354,7 @@
         self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
         defer { self.decoder.codingPath.removeLast() }
 
-        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+        guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
             throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
         }
 
@@ -1516,8 +1516,8 @@
     }
 
     public func decode<T : Decodable>(_ type: T.Type) throws -> T {
-        try expectNonNull(T.self)
-        return try self.unbox(self.storage.topContainer, as: T.self)!
+        try expectNonNull(type)
+        return try self.unbox(self.storage.topContainer, as: type)!
     }
 }
 
@@ -1756,15 +1756,15 @@
 
     fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
         let decoded: T
-        if T.self == Date.self || T.self == NSDate.self {
+        if type == Date.self || type == NSDate.self {
             guard let date = try self.unbox(value, as: Date.self) else { return nil }
             decoded = date as! T
-        } else if T.self == Data.self || T.self == NSData.self {
+        } else if type == Data.self || type == NSData.self {
             guard let data = try self.unbox(value, as: Data.self) else { return nil }
             decoded = data as! T
         } else {
             self.storage.push(container: value)
-            decoded = try T(from: self)
+            decoded = try type.init(from: self)
             self.storage.popContainer()
         }
 
diff --git a/stdlib/public/SDK/Intents/INRideOption.swift b/stdlib/public/SDK/Intents/INRideOption.swift
index c6b8959..4ae1f29 100644
--- a/stdlib/public/SDK/Intents/INRideOption.swift
+++ b/stdlib/public/SDK/Intents/INRideOption.swift
@@ -26,7 +26,7 @@
 extension _INRideOptionMeteredFare {
   @available(swift, obsoleted: 4)
   @nonobjc
-  public final var usesMeteredFare: NSNumber? {
+  public var usesMeteredFare: NSNumber? {
     get {
       return __usesMeteredFare
     }
diff --git a/stdlib/public/SDK/Metal/CMakeLists.txt b/stdlib/public/SDK/Metal/CMakeLists.txt
index f3fe951..4ea2491 100644
--- a/stdlib/public/SDK/Metal/CMakeLists.txt
+++ b/stdlib/public/SDK/Metal/CMakeLists.txt
@@ -4,7 +4,7 @@
 add_swift_library(swiftMetal ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
     Metal.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch Foundation IOKit ObjectiveC XPC # auto-updated
diff --git a/stdlib/public/SDK/MetalKit/CMakeLists.txt b/stdlib/public/SDK/MetalKit/CMakeLists.txt
index b0a2013..a1f8a96 100644
--- a/stdlib/public/SDK/MetalKit/CMakeLists.txt
+++ b/stdlib/public/SDK/MetalKit/CMakeLists.txt
@@ -4,7 +4,7 @@
 add_swift_library(swiftMetalKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
     MetalKit.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_OSX Darwin AppKit CoreData CoreFoundation CoreGraphics CoreImage Dispatch Foundation IOKit Metal ModelIO ObjectiveC QuartzCore simd XPC # auto-updated
diff --git a/stdlib/public/SDK/SceneKit/CMakeLists.txt b/stdlib/public/SDK/SceneKit/CMakeLists.txt
index 0f3a360..72b8e44 100644
--- a/stdlib/public/SDK/SceneKit/CMakeLists.txt
+++ b/stdlib/public/SDK/SceneKit/CMakeLists.txt
@@ -4,7 +4,7 @@
 add_swift_library(swiftSceneKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
   SceneKit.swift.gyb
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_OSX Darwin AppKit CoreData CoreGraphics CoreImage Dispatch Foundation GLKit IOKit ObjectiveC QuartzCore simd XPC # auto-updated
diff --git a/stdlib/public/SDK/UIKit/CMakeLists.txt b/stdlib/public/SDK/UIKit/CMakeLists.txt
index 0022cb83..d8df4eb 100644
--- a/stdlib/public/SDK/UIKit/CMakeLists.txt
+++ b/stdlib/public/SDK/UIKit/CMakeLists.txt
@@ -6,7 +6,7 @@
   UIKit.swift
   UIKit_FoundationExtensions.swift.gyb
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+  SWIFT_COMPILE_FLAGS ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} -swift-version 4
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation CoreGraphics CoreImage Dispatch Foundation ObjectiveC QuartzCore os # auto-updated
diff --git a/stdlib/public/SDK/UIKit/UIKit.swift b/stdlib/public/SDK/UIKit/UIKit.swift
index 3823d39..9be02a5 100644
--- a/stdlib/public/SDK/UIKit/UIKit.swift
+++ b/stdlib/public/SDK/UIKit/UIKit.swift
@@ -57,6 +57,52 @@
 
 extension UIOffset : Equatable {}
 
+//===----------------------------------------------------------------------===//
+// Numeric backed types
+//===----------------------------------------------------------------------===//
+
+@available(swift 4)
+public protocol _UIKitNumericRawRepresentable : RawRepresentable, Comparable where RawValue: Comparable & Numeric {}
+
+extension _UIKitNumericRawRepresentable {
+
+  public static func <(lhs: Self, rhs: Self) -> Bool {
+    return lhs.rawValue < rhs.rawValue
+  }
+
+  public static func +(lhs: Self, rhs: RawValue) -> Self {
+    return Self(rawValue: lhs.rawValue + rhs)!
+  }
+
+  public static func +(lhs: RawValue, rhs: Self) -> Self {
+    return Self(rawValue: lhs + rhs.rawValue)!
+  }
+
+  public static func -(lhs: Self, rhs: RawValue) -> Self {
+    return Self(rawValue: lhs.rawValue - rhs)!
+  }
+
+  public static func -(lhs: Self, rhs: Self) -> RawValue {
+    return lhs.rawValue - rhs.rawValue
+  }
+
+  public static func +=(lhs: inout Self, rhs: RawValue) {
+    lhs = Self(rawValue: lhs.rawValue + rhs)!
+  }
+
+  public static func -=(lhs: inout Self, rhs: RawValue) {
+    lhs = Self(rawValue: lhs.rawValue - rhs)!
+  }
+}
+
+@available(swift 4)
+extension UIFont.Weight : _UIKitNumericRawRepresentable {}
+
+#if !os(watchOS)
+@available(swift 4)
+extension UILayoutPriority : _UIKitNumericRawRepresentable {}
+#endif
+
 // These are un-imported macros in UIKit.
 
 //===----------------------------------------------------------------------===//
@@ -247,6 +293,7 @@
 
 #if !os(watchOS) // UIContentSizeCategory not available on watchOS
 extension UIContentSizeCategory {
+
     @available(iOS 11.0, tvOS 11.0,  *)
     public var isAccessibilityCategory: Bool {
         return __UIContentSizeCategoryIsAccessibilityCategory(self)
diff --git a/stdlib/public/SDK/XCTest/XCTest.swift b/stdlib/public/SDK/XCTest/XCTest.swift
index 918b4b9..01a8494 100644
--- a/stdlib/public/SDK/XCTest/XCTest.swift
+++ b/stdlib/public/SDK/XCTest/XCTest.swift
@@ -42,7 +42,7 @@
 @available(macOS 10.11, *)
 public extension XCUIElement {
   /// Types a single key from the XCUIKeyboardKey enumeration with the specified modifier flags.
-  @nonobjc public func typeKey(_ key: XCUIKeyboardKey, modifierFlags: XCUIKeyModifierFlags) {
+  @nonobjc public func typeKey(_ key: XCUIKeyboardKey, modifierFlags: XCUIElement.KeyModifierFlags) {
     // Call the version of the method defined in XCTest.framework.
     typeKey(key.rawValue, modifierFlags: modifierFlags)
   }
@@ -55,11 +55,11 @@
 func _XCTRegisterFailure(_ expected: Bool, _ condition: String, _ message: @autoclosure () -> String, _ file: StaticString, _ line: UInt) {
   // Call the real _XCTFailureHandler.
   let test = _XCTCurrentTestCase()
-  _XCTPreformattedFailureHandler(test, expected, file.description, line, condition, message())
+  _XCTPreformattedFailureHandler(test, expected, file.description, Int(line), condition, message())
 }
 
 /// Produce a failure description for the given assertion type.
-func _XCTFailureDescription(_ assertionType: _XCTAssertionType, _ formatIndex: UInt, _ expressionStrings: CVarArg...) -> String {
+func _XCTFailureDescription(_ assertionType: _XCTAssertionType, _ formatIndex: Int, _ expressionStrings: CVarArg...) -> String {
   // In order to avoid revlock/submission issues between XCTest and the Swift XCTest overlay,
   // we are using the convention with _XCTFailureFormat that (formatIndex >= 100) should be
   // treated just like (formatIndex - 100), but WITHOUT the expression strings. (Swift can't
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 260d04e..6aa7709 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -1,3 +1,6 @@
+# HACK: Force this library to build with undefined symbols.
+string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+
 # libswiftRemoteMirror.dylib should not have runtime dependencies; it's
 # always built as a shared library.
 if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index 29b78b9..8c9ae82 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -16,8 +16,7 @@
 #include "System.h"
 
 #define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
-// TODO: Should be 8
-#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 12
+#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 8
 
 #ifdef __cplusplus
 #include <type_traits>
@@ -39,12 +38,12 @@
   InlineRefCounts refCounts
 
 /// The Swift heap-object header.
+/// This must match RefCountedStructTy in IRGen.
 struct HeapObject {
   /// This is always a valid pointer to a metadata object.
   HeapMetadata const *metadata;
 
   SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
-  // FIXME: allocate two words of metadata on 32-bit platforms
 
 #ifdef __cplusplus
   HeapObject() = default;
@@ -75,15 +74,8 @@
 static_assert(std::is_trivially_destructible<HeapObject>::value,
               "HeapObject must be trivially destructible");
 
-// FIXME: small header for 32-bit
-//static_assert(sizeof(HeapObject) == 2*sizeof(void*),
-//              "HeapObject must be two pointers long");
-//
-static_assert(sizeof(HeapObject) ==
-  (sizeof(void*) == 8 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 :
-   sizeof(void*) == 4 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 :
-   0 && "unexpected pointer size"),
-  "HeapObject must match ABI heap object header size");
+static_assert(sizeof(HeapObject) == 2*sizeof(void*),
+              "HeapObject must be two pointers long");
 
 static_assert(alignof(HeapObject) == alignof(void*),
               "HeapObject must be pointer-aligned");
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 211de02..e1cd7aa 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -15,19 +15,17 @@
 #include "Visibility.h"
 #include "SwiftStdint.h"
 
+// This definition is a placeholder for importing into Swift.
+// It provides size and alignment but cannot be manipulated safely there.
+typedef struct {
+  __swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
+} InlineRefCountsPlaceholder;
+
 #if !defined(__cplusplus)
 
-// These definitions are placeholders for importing into Swift.
-// They provide size and alignment but cannot be manipulated safely there.
+typedef InlineRefCountsPlaceholder InlineRefCounts;
 
-typedef struct {
-  _Alignas(__swift_uintptr_t) __swift_uint32_t refCounts1 SWIFT_ATTRIBUTE_UNAVAILABLE;
-  __swift_uint32_t refCounts2 SWIFT_ATTRIBUTE_UNAVAILABLE;
-} InlineRefCounts;
-
-// not __cplusplus
 #else
-// __cplusplus
 
 #include <type_traits>
 #include <atomic>
@@ -733,11 +731,6 @@
 template <typename RefCountBits>
 class RefCounts {
   std::atomic<RefCountBits> refCounts;
-#if __POINTER_WIDTH__ == 32
-  // FIXME: hack - something somewhere is assuming a 3-word header on 32-bit
-  // See also other fixmes marked "small header for 32-bit"
-  uintptr_t : 32;
-#endif
 
   // Out-of-line slow paths.
 
@@ -1572,15 +1565,11 @@
 #endif
 
 // These assertions apply to both the C and the C++ declarations.
-_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
-  "InlineRefCounts must be pointer-aligned");
-// FIXME: small header for 32-bit
-#if 0
+_Static_assert(sizeof(InlineRefCounts) == sizeof(InlineRefCountsPlaceholder),
+  "InlineRefCounts and InlineRefCountsPlaceholder must match");
 _Static_assert(sizeof(InlineRefCounts) == sizeof(__swift_uintptr_t),
   "InlineRefCounts must be pointer-sized");
-#else
-_Static_assert(sizeof(InlineRefCounts) == 2*sizeof(__swift_uint32_t),
-  "InlineRefCounts must be 8 bytes");
-#endif
+_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
+  "InlineRefCounts must be pointer-aligned");
 
 #endif
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index c9eeeee..d80b233 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -178,7 +178,7 @@
 /// can store any kind of elements---from integers to strings to classes.
 ///
 /// Swift makes it easy to create arrays in your code using an array literal:
-/// simply surround a comma separated list of values with square brackets.
+/// simply surround a comma-separated list of values with square brackets.
 /// Without any other information, Swift creates an array that includes the
 /// specified values, automatically inferring the array's `Element` type. For
 /// example:
@@ -2181,57 +2181,55 @@
 // that are the same, e.g. Array<Int> and Array<Int>, not
 // ArraySlice<Int> and Array<Int>.
 
-/// Returns `true` if these arrays contain the same elements.
-@_inlineable
-public func == <Element : Equatable>(
-  lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
-  let lhsCount = lhs.count
-  if lhsCount != rhs.count {
-    return false
-  }
+extension ${Self} : Equatable where Element : Equatable {
+  /// Returns `true` if these arrays contain the same elements.
+  @_inlineable
+  public static func ==(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+    let lhsCount = lhs.count
+    if lhsCount != rhs.count {
+      return false
+    }
 
-  // Test referential equality.
-  if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+    // Test referential equality.
+    if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+      return true
+    }
+
+  %if Self == 'ArraySlice':
+
+    var streamLHS = lhs.makeIterator()
+    var streamRHS = rhs.makeIterator()
+
+    var nextLHS = streamLHS.next()
+    while nextLHS != nil {
+      let nextRHS = streamRHS.next()
+      if nextLHS != nextRHS {
+        return false
+      }
+      nextLHS = streamLHS.next()
+    }
+
+  %else:
+
+    _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
+    _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
+
+    // We know that lhs.count == rhs.count, compare element wise.
+    for idx in 0..<lhsCount {
+      if lhs[idx] != rhs[idx] {
+        return false
+      }
+    }
+  %end
+
     return true
   }
 
-%if Self == 'ArraySlice':
-
-  var streamLHS = lhs.makeIterator()
-  var streamRHS = rhs.makeIterator()
-
-  var nextLHS = streamLHS.next()
-  while nextLHS != nil {
-    let nextRHS = streamRHS.next()
-    if nextLHS != nextRHS {
-      return false
-    }
-    nextLHS = streamLHS.next()
+  /// Returns `true` if the arrays do not contain the same elements.
+  @_inlineable
+  public static func !=(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+    return !(lhs == rhs)
   }
-
-%else:
-
-  _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
-  _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
-
-  // We know that lhs.count == rhs.count, compare element wise.
-  for idx in 0..<lhsCount {
-    if lhs[idx] != rhs[idx] {
-      return false
-    }
-  }
-%end
-
-  return true
-}
-
-/// Returns `true` if the arrays do not contain the same elements.
-@_inlineable
-public func != <Element : Equatable>(
-  lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
-  return !(lhs == rhs)
 }
 
 extension ${Self} {
diff --git a/stdlib/public/core/Builtin.swift b/stdlib/public/core/Builtin.swift
index 72e2592..2f06587 100644
--- a/stdlib/public/core/Builtin.swift
+++ b/stdlib/public/core/Builtin.swift
@@ -144,8 +144,13 @@
   return !(lhs == rhs)
 }
 
-/// Returns `true` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are identical.
+///
+/// - Parameters:
+///   - t0: A type to compare.
+///   - t1: Another type to compare.
+/// - Returns: `true` if both `t0` and `t1` are `nil` or if they represent the
+///   same type; otherwise, `false`.
 @_inlineable
 public func == (t0: Any.Type?, t1: Any.Type?) -> Bool {
   switch (t0, t1) {
@@ -156,8 +161,13 @@
   }
 }
 
-/// Returns `false` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are not identical.
+///
+/// - Parameters:
+///   - t0: A type to compare.
+///   - t1: Another type to compare.
+/// - Returns: `true` if one, but not both, of `t0` and `t1` are `nil`, or if
+///   they represent different types; otherwise, `false`.
 @_inlineable
 public func != (t0: Any.Type?, t1: Any.Type?) -> Bool {
   return !(t0 == t1)
diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift
index 018b1da..0d3af0d 100644
--- a/stdlib/public/core/CTypes.swift
+++ b/stdlib/public/core/CTypes.swift
@@ -42,17 +42,19 @@
 /// The C 'int' type.
 public typealias CInt = Int32
 
-/// The C 'long' type.
 #if os(Windows) && arch(x86_64)
+/// The C 'long' type.
 public typealias CLong = Int32
 #else
+/// The C 'long' type.
 public typealias CLong = Int
 #endif
 
-/// The C 'long long' type.
 #if os(Windows) && arch(x86_64)
+/// The C 'long long' type.
 public typealias CLongLong = Int
 #else
+/// The C 'long long' type.
 public typealias CLongLong = Int64
 #endif
 
@@ -200,7 +202,7 @@
   }
 }
 
-/// The corresponding Swift type to `va_list` in imported C APIs.
+/// A wrapper around a C `va_list` pointer.
 @_fixed_layout
 public struct CVaListPointer {
   @_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 9526057..dcad518 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -18,8 +18,7 @@
   where
   // FIXME(ABI)#176 (Type checker)
   // WORKAROUND rdar://25214598 - should be Bound : Strideable
-  Bound : _Strideable & Comparable,
-  Bound.Stride : BinaryInteger {
+  Bound : _Strideable & Comparable {
   case pastEnd
   case inRange(Bound)
 }
@@ -36,7 +35,7 @@
   // CountableClosedRange is not interchangeable with CountableRange in all
   // contexts.
   Bound : _Strideable & Comparable,
-  Bound.Stride : SignedInteger {
+  Bound.Stride : SignedNumeric {
   /// Creates the "past the end" position.
   @_inlineable
   @_versioned
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index 462c6cc..e7e2e05 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -1166,8 +1166,8 @@
 
 // An implementation of _KeyedDecodingContainerBase and _KeyedDecodingContainerBox are given at the bottom of this file.
 
-/// A concrete container that provides a view into an decoder's storage, making
-/// the encoded properties of an decodable type accessible by keys.
+/// A concrete container that provides a view into a decoder's storage, making
+/// the encoded properties of a decodable type accessible by keys.
 @_fixed_layout // FIXME(sil-serialize-all)
 public struct KeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
     public typealias Key = K
@@ -2307,7 +2307,8 @@
     mutating func encode<T : Encodable>(_ value: T) throws
 }
 
-/// A `SingleValueDecodingContainer` is a container which can support the storage and direct decoding of a single non-keyed value.
+/// A container that can support the storage and direct decoding of a single
+/// nonkeyed value.
 public protocol SingleValueDecodingContainer {
     /// The path of coding keys taken to get to this point in encoding.
     var codingPath: [CodingKey] { get }
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 567c036..79c021f 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -559,11 +559,11 @@
     // in angles in the wrong quadrant if users aren't careful.  This is
     // not a problem for Double or Float80, as pi rounds down in both of
     // those formats.
-    return Float(0x1.921fb4p1)
+    return 0x1.921fb4p1
 %elif bits == 64:
-    return Double(0x1.921fb54442d18p1)
+    return 0x1.921fb54442d18p1
 %elif bits == 80:
-    return Float80(0x1.921fb54442d1846ap1)
+    return 0x1.921fb54442d1846ap1
 %end
   }
 
@@ -1503,8 +1503,9 @@
   public init?(exactly value: ${That}) {
     _value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(value._value)
 
-%   if srcBits < SignificandBitCount:
-    if ${That}(self) != value {
+%   if srcBits >= SignificandBitCount:
+    guard let roundTrip = ${That}(exactly: self),
+      roundTrip == value else {
       return nil
     }
 %   end
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index 36f88c8..12433e3 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -2708,7 +2708,7 @@
   }
 }
 
-extension Dictionary where Value : Equatable {
+extension Dictionary : Equatable where Value : Equatable {
   @_inlineable // FIXME(sil-serialize-all)
   public static func == (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
     switch (lhs._variantBuffer, rhs._variantBuffer) {
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 020ff15..2f8a39d 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -1620,8 +1620,8 @@
 // on `Self` to prevent dynamically-typed methods from being inherited by
 // statically-typed key paths.
 
-/// This protocol is an implementation detail of key path expressions; do not
-/// use it directly.
+/// An implementation detail of key path expressions; do not use this protocol
+/// directly.
 @_show_in_interface
 public protocol _AppendKeyPath {}
 
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 1f41bd5..92f5b09 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -12,15 +12,31 @@
 // FIXME: ExistentialCollection needs to be supported before this will work
 // without the ObjC Runtime.
 
-/// Representation of the sub-structure and optional "display style"
-/// of any arbitrary subject instance.
+/// A representation of the substructure and display style of an instance of
+/// any type.
 ///
-/// Describes the parts---such as stored properties, collection
-/// elements, tuple elements, or the active enumeration case---that
-/// make up a particular instance.  May also supply a "display style"
-/// property that suggests how this structure might be rendered.
+/// A mirror describes the parts that make up a particular instance, such as
+/// the instance's stored properties, collection or tuple elements, or its
+/// active enumeration case. Mirrors also provide a "display style" property
+/// that suggests how this mirror might be rendered.
 ///
-/// Mirrors are used by playgrounds and the debugger.
+/// Playgrounds and the debugger use the `Mirror` type to display
+/// representations of values of any type. For example, when you pass an
+/// instance to the `dump(_:_:_:_:)` function, a mirror is used to render that
+/// instance's runtime contents.
+///
+///     struct Point {
+///         let x: Int, y: Int
+///     }
+///
+///     let p = Point(x: 21, y: 30)
+///     print(String(reflecting: p))
+///     // Prints "▿ Point
+///     //           - x: 21
+///     //           - y: 30"
+///
+/// To customize the mirror representation of a custom type, add conformance to
+/// the `CustomReflectable` protocol.
 @_fixed_layout // FIXME(sil-serialize-all)
 public struct Mirror {
   /// Representation of descendant classes that don't override
@@ -46,56 +62,58 @@
     case suppressed
   }
 
-  /// Representation of ancestor classes.
+  /// The representation to use for ancestor classes.
   ///
-  /// A `CustomReflectable` class can control how its mirror will
-  /// represent ancestor classes by initializing the mirror with a
-  /// `AncestorRepresentation`.  This setting has no effect on mirrors
+  /// A class that conforms to the `CustomReflectable` protocol can control how
+  /// its mirror represents ancestor classes by initializing the mirror
+  /// with an `AncestorRepresentation`. This setting has no effect on mirrors
   /// reflecting value type instances.
   public enum AncestorRepresentation {
 
-    /// Generate a default mirror for all ancestor classes.
+    /// Generates a default mirror for all ancestor classes.
     ///
-    /// This case is the default.
+    /// This case is the default when initializing a `Mirror` instance.
     ///
-    /// - Note: This option generates default mirrors even for
-    ///   ancestor classes that may implement `CustomReflectable`'s
-    ///   `customMirror` requirement.  To avoid dropping an ancestor class
-    ///   customization, an override of `customMirror` should pass
-    ///   `ancestorRepresentation: .Customized(super.customMirror)` when
-    ///   initializing its `Mirror`.
+    /// When you use this option, a subclass's mirror generates default mirrors
+    /// even for ancestor classes that conform to the `CustomReflectable`
+    /// protocol. To avoid dropping the customization provided by ancestor
+    /// classes, an override of `customMirror` should pass
+    /// `.customized({ super.customMirror })` as `ancestorRepresentation` when
+    /// initializing its mirror.
     case generated
 
-    /// Use the nearest ancestor's implementation of `customMirror` to
-    /// create a mirror for that ancestor.  Other classes derived from
-    /// such an ancestor are given a default mirror.
+    /// Uses the nearest ancestor's implementation of `customMirror` to create
+    /// a mirror for that ancestor.
     ///
-    /// The payload for this option should always be
-    /// "`{ super.customMirror }`":
+    /// Other classes derived from such an ancestor are given a default mirror.
+    /// The payload for this option should always be `{ super.customMirror }`:
     ///
     ///     var customMirror: Mirror {
-    ///       return Mirror(
-    ///         self,
-    ///         children: ["someProperty": self.someProperty],
-    ///         ancestorRepresentation: .Customized({ super.customMirror })) // <==
+    ///         return Mirror(
+    ///             self,
+    ///             children: ["someProperty": self.someProperty],
+    ///             ancestorRepresentation: .customized({ super.customMirror })) // <==
     ///     }
     case customized(() -> Mirror)
 
-    /// Suppress the representation of all ancestor classes.  The
-    /// resulting `Mirror`'s `superclassMirror` is `nil`.
+    /// Suppresses the representation of all ancestor classes.
+    ///
+    /// In a mirror created with this ancestor representation, the
+    /// `superclassMirror` property is `nil`.
     case suppressed
   }
 
-  /// Reflect upon the given `subject`.
+  /// Creates a mirror that reflects on the given instance.
   ///
-  /// If the dynamic type of `subject` conforms to `CustomReflectable`,
-  /// the resulting mirror is determined by its `customMirror` property.
+  /// If the dynamic type of `subject` conforms to `CustomReflectable`, the
+  /// resulting mirror is determined by its `customMirror` property.
   /// Otherwise, the result is generated by the language.
   ///
-  /// - Note: If the dynamic type of `subject` has value semantics,
-  ///   subsequent mutations of `subject` will not observable in
-  ///   `Mirror`.  In general, though, the observability of such
-  /// mutations is unspecified.
+  /// If the dynamic type of `subject` has value semantics, subsequent
+  /// mutations of `subject` will not observable in `Mirror`.  In general,
+  /// though, the observability of mutations is unspecified.
+  ///
+  /// - Parameter subject: The instance for which to create a mirror.
   @_inlineable // FIXME(sil-serialize-all)
   public init(reflecting subject: Any) {
     if case let customized as CustomReflectable = subject {
@@ -107,36 +125,33 @@
     }
   }
 
-  /// An element of the reflected instance's structure.  The optional
-  /// `label` may be used when appropriate, e.g. to represent the name
-  /// of a stored property or of an active `enum` case, and will be
-  /// used for lookup when `String`s are passed to the `descendant`
-  /// method.
+  /// An element of the reflected instance's structure.
+  ///
+  /// When the `label` component in not `nil`, it may represent the name of a
+  /// stored property or an active `enum` case. If you pass strings to the
+  /// `descendant(_:_:)` method, labels are used for lookup.
   public typealias Child = (label: String?, value: Any)
 
-  /// The type used to represent sub-structure.
+  /// The type used to represent substructure.
   ///
-  /// Depending on your needs, you may find it useful to "upgrade"
-  /// instances of this type to `AnyBidirectionalCollection` or
-  /// `AnyRandomAccessCollection`.  For example, to display the last
-  /// 20 children of a mirror if they can be accessed efficiently, you
-  /// might write:
+  /// When working with a mirror that reflects a bidirectional or random access
+  /// collection, you may find it useful to "upgrade" instances of this type
+  /// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For
+  /// example, to display the last twenty children of a mirror if they can be
+  /// accessed efficiently, you write the following code:
   ///
   ///     if let b = AnyBidirectionalCollection(someMirror.children) {
-  ///       var i = xs.index(b.endIndex, offsetBy: -20,
-  ///         limitedBy: b.startIndex) ?? b.startIndex
-  ///       while i != xs.endIndex {
-  ///          print(b[i])
-  ///          b.formIndex(after: &i)
-  ///       }
+  ///         for element in b.suffix(20) {
+  ///             print(element)
+  ///         }
   ///     }
   public typealias Children = AnyCollection<Child>
 
-  /// A suggestion of how a `Mirror`'s `subject` is to be interpreted.
+  /// A suggestion of how a mirror's subject is to be interpreted.
   ///
   /// Playgrounds and the debugger will show a representation similar
   /// to the one used for instances of the kind indicated by the
-  /// `DisplayStyle` case name when the `Mirror` is used for display.
+  /// `DisplayStyle` case name when the mirror is used for display.
   @_fixed_layout // FIXME(sil-serialize-all)
   public enum DisplayStyle {
     case `struct`, `class`, `enum`, tuple, optional, collection
@@ -200,26 +215,31 @@
     return Mirror._noSuperclassMirror
   }
   
-  /// Represent `subject` with structure described by `children`,
-  /// using an optional `displayStyle`.
+  /// Creates a mirror representing the given subject with a specified
+  /// structure.
   ///
-  /// If `subject` is not a class instance, `ancestorRepresentation`
-  /// is ignored.  Otherwise, `ancestorRepresentation` determines
+  /// You use this initializer from within your type's `customMirror`
+  /// implementation to create a customized mirror.
+  ///
+  /// If `subject` is a class instance, `ancestorRepresentation` determines
   /// whether ancestor classes will be represented and whether their
-  /// `customMirror` implementations will be used.  By default, a
-  /// representation is automatically generated and any `customMirror`
-  /// implementation is bypassed.  To prevent bypassing customized
-  /// ancestors, `customMirror` overrides should initialize the
-  /// `Mirror` with:
+  /// `customMirror` implementations will be used. By default, the
+  /// `customMirror` implementation of any ancestors is ignored. To prevent
+  /// bypassing customized ancestors, pass
+  /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+  /// parameter when implementing your type's `customMirror` property.
   ///
-  ///     ancestorRepresentation: .customized({ super.customMirror })
-  ///
-  /// - Note: The traversal protocol modeled by `children`'s indices
-  ///   (`ForwardIndex`, `BidirectionalIndex`, or
-  ///   `RandomAccessIndex`) is captured so that the resulting
-  /// `Mirror`'s `children` may be upgraded later.  See the failable
-  /// initializers of `AnyBidirectionalCollection` and
-  /// `AnyRandomAccessCollection` for details.
+  /// - Parameters:
+  ///   - subject: The instance to represent in the new mirror.
+  ///   - children: The structure to use for the mirror. The collection
+  ///     traversal modeled by `children` is captured so that the resulting
+  ///     mirror's children may be upgraded to a bidirectional or random
+  ///     access collection later. See the `children` property for details.
+  ///   - displayStyle: The preferred display style for the mirror when
+  ///     presented in the debugger or in a playground. The default is `nil`.
+  ///   - ancestorRepresentation: The means of generating the subject's
+  ///     ancestor representation. `ancestorRepresentation` is ignored if
+  ///     `subject` is not a class instance. The default is `.generated`.
   @_inlineable // FIXME(sil-serialize-all)
   public init<Subject, C : Collection>(
     _ subject: Subject,
@@ -239,36 +259,33 @@
       = subject is CustomLeafReflectable ? .suppressed : .generated
   }
 
-  /// Represent `subject` with child values given by
-  /// `unlabeledChildren`, using an optional `displayStyle`.  The
-  /// result's child labels will all be `nil`.
+  /// Creates a mirror representing the given subject with unlabeled children.
   ///
-  /// This initializer is especially useful for the mirrors of
-  /// collections, e.g.:
+  /// You use this initializer from within your type's `customMirror`
+  /// implementation to create a customized mirror, particularly for custom
+  /// types that are collections. The labels of the resulting mirror's
+  /// `children` collection are all `nil`.
   ///
-  ///     extension MyArray : CustomReflectable {
-  ///       var customMirror: Mirror {
-  ///         return Mirror(self, unlabeledChildren: self, displayStyle: .collection)
-  ///       }
-  ///     }
-  ///
-  /// If `subject` is not a class instance, `ancestorRepresentation`
-  /// is ignored.  Otherwise, `ancestorRepresentation` determines
+  /// If `subject` is a class instance, `ancestorRepresentation` determines
   /// whether ancestor classes will be represented and whether their
-  /// `customMirror` implementations will be used.  By default, a
-  /// representation is automatically generated and any `customMirror`
-  /// implementation is bypassed.  To prevent bypassing customized
-  /// ancestors, `customMirror` overrides should initialize the
-  /// `Mirror` with:
+  /// `customMirror` implementations will be used. By default, the
+  /// `customMirror` implementation of any ancestors is ignored. To prevent
+  /// bypassing customized ancestors, pass
+  /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+  /// parameter when implementing your type's `customMirror` property.
   ///
-  ///     ancestorRepresentation: .Customized({ super.customMirror })
-  ///
-  /// - Note: The traversal protocol modeled by `children`'s indices
-  ///   (`ForwardIndex`, `BidirectionalIndex`, or
-  ///   `RandomAccessIndex`) is captured so that the resulting
-  /// `Mirror`'s `children` may be upgraded later.  See the failable
-  /// initializers of `AnyBidirectionalCollection` and
-  /// `AnyRandomAccessCollection` for details.
+  /// - Parameters:
+  ///   - subject: The instance to represent in the new mirror.
+  ///   - unlabeledChildren: The children to use for the mirror. The collection
+  ///     traversal modeled by `unlabeledChildren` is captured so that the
+  ///     resulting mirror's children may be upgraded to a bidirectional or
+  ///     random access collection later. See the `children` property for
+  ///     details.
+  ///   - displayStyle: The preferred display style for the mirror when
+  ///     presented in the debugger or in a playground. The default is `nil`.
+  ///   - ancestorRepresentation: The means of generating the subject's
+  ///     ancestor representation. `ancestorRepresentation` is ignored if
+  ///     `subject` is not a class instance. The default is `.generated`.
   @_inlineable // FIXME(sil-serialize-all)
   public init<Subject, C : Collection>(
     _ subject: Subject,
@@ -291,29 +308,35 @@
       = subject is CustomLeafReflectable ? .suppressed : .generated
   }
 
-  /// Represent `subject` with labeled structure described by
-  /// `children`, using an optional `displayStyle`.
+  /// Creates a mirror representing the given subject using a dictionary
+  /// literal for the structure.
   ///
-  /// Pass a dictionary literal with `String` keys as `children`.  Be
-  /// aware that although an *actual* `Dictionary` is
-  /// arbitrarily-ordered, the ordering of the `Mirror`'s `children`
-  /// will exactly match that of the literal you pass.
+  /// You use this initializer from within your type's `customMirror`
+  /// implementation to create a customized mirror. Pass a dictionary literal
+  /// with string keys as `children`. Although an *actual* dictionary is
+  /// arbitrarily-ordered, when you create a mirror with a dictionary literal,
+  /// the ordering of the mirror's `children` will exactly match that of the
+  /// literal you pass.
   ///
-  /// If `subject` is not a class instance, `ancestorRepresentation`
-  /// is ignored.  Otherwise, `ancestorRepresentation` determines
+  /// If `subject` is a class instance, `ancestorRepresentation` determines
   /// whether ancestor classes will be represented and whether their
-  /// `customMirror` implementations will be used.  By default, a
-  /// representation is automatically generated and any `customMirror`
-  /// implementation is bypassed.  To prevent bypassing customized
-  /// ancestors, `customMirror` overrides should initialize the
-  /// `Mirror` with:
+  /// `customMirror` implementations will be used. By default, the
+  /// `customMirror` implementation of any ancestors is ignored. To prevent
+  /// bypassing customized ancestors, pass
+  /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+  /// parameter when implementing your type's `customMirror` property.
   ///
-  ///     ancestorRepresentation: .customized({ super.customMirror })
-  ///
-  /// - Note: The resulting `Mirror`'s `children` may be upgraded to
-  ///   `AnyRandomAccessCollection` later.  See the failable
-  ///   initializers of `AnyBidirectionalCollection` and
-  /// `AnyRandomAccessCollection` for details.
+  /// - Parameters:
+  ///   - subject: The instance to represent in the new mirror.
+  ///   - children: A dictionary literal to use as the structure for the
+  ///     mirror. The `children` collection of the resulting mirror may be
+  ///     upgraded to a random access collection later. See the `children`
+  ///     property for details.
+  ///   - displayStyle: The preferred display style for the mirror when
+  ///     presented in the debugger or in a playground. The default is `nil`.
+  ///   - ancestorRepresentation: The means of generating the subject's
+  ///     ancestor representation. `ancestorRepresentation` is ignored if
+  ///     `subject` is not a class instance. The default is `.generated`.
   @_inlineable // FIXME(sil-serialize-all)
   public init<Subject>(
     _ subject: Subject,
@@ -335,7 +358,7 @@
 
   /// The static type of the subject being reflected.
   ///
-  /// This type may differ from the subject's dynamic type when `self`
+  /// This type may differ from the subject's dynamic type when this mirror
   /// is the `superclassMirror` of another mirror.
   public let subjectType: Any.Type
 
@@ -343,9 +366,10 @@
   /// reflected subject.
   public let children: Children
 
-  /// Suggests a display style for the reflected subject.
+  /// A suggested display style for the reflected subject.
   public let displayStyle: DisplayStyle?
 
+  /// A mirror of the subject's superclass, if one exists.
   @_inlineable // FIXME(sil-serialize-all)
   public var superclassMirror: Mirror? {
     return _makeSuperclassMirror()
@@ -359,7 +383,7 @@
 
 /// A type that explicitly supplies its own mirror.
 ///
-/// You can create a mirror for any type using the `Mirror(reflect:)`
+/// You can create a mirror for any type using the `Mirror(reflecting:)`
 /// initializer, but if you are not satisfied with the mirror supplied for
 /// your type by default, you can make it conform to `CustomReflectable` and
 /// return a custom `Mirror` instance.
@@ -383,9 +407,10 @@
 ///
 /// Do not declare new conformances to this protocol; they will not
 /// work as expected.
-// FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and you shouldn't be able to
-// create conformances.
-public protocol MirrorPath {}
+public protocol MirrorPath {
+  // FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and
+  // you shouldn't be able to create conformances.
+}
 extension Int : MirrorPath {}
 extension String : MirrorPath {}
 
@@ -405,42 +430,50 @@
     internal var customMirror: Mirror { return mirror }
   }
 
-  /// Return a specific descendant of the reflected subject, or `nil`
-  /// Returns a specific descendant of the reflected subject, or `nil`
-  /// if no such descendant exists.
+  /// Returns a specific descendant of the reflected subject, or `nil` if no
+  /// such descendant exists.
   ///
-  /// A `String` argument selects the first `Child` with a matching label.
-  /// An integer argument *n* select the *n*th `Child`.  For example:
+  /// Pass a variadic list of string and integer arguments. Each string
+  /// argument selects the first child with a matching label. Each integer
+  /// argument selects the child at that offset. For example, passing
+  /// `1, "two", 3` as arguments to `myMirror.descendant(_:_:)` is equivalent
+  /// to:
   ///
-  ///     var d = Mirror(reflecting: x).descendant(1, "two", 3)
-  ///
-  /// is equivalent to:
-  ///
-  ///     var d = nil
-  ///     let children = Mirror(reflecting: x).children
-  ///     if let p0 = children.index(children.startIndex,
-  ///       offsetBy: 1, limitedBy: children.endIndex) {
-  ///       let grandChildren = Mirror(reflecting: children[p0].value).children
-  ///       SeekTwo: for g in grandChildren {
-  ///         if g.label == "two" {
-  ///           let greatGrandChildren = Mirror(reflecting: g.value).children
-  ///           if let p1 = greatGrandChildren.index(
-  ///             greatGrandChildren.startIndex,
-  ///             offsetBy: 3, limitedBy: greatGrandChildren.endIndex) {
-  ///             d = greatGrandChildren[p1].value
-  ///           }
-  ///           break SeekTwo
+  ///     var result: Any? = nil
+  ///     let children = myMirror.children
+  ///     if let i0 = children.index(
+  ///         children.startIndex, offsetBy: 1, limitedBy: children.endIndex),
+  ///         i0 != children.endIndex
+  ///     {
+  ///         let grandChildren = Mirror(reflecting: children[i0].value).children
+  ///         if let i1 = grandChildren.index(where: { $0.label == "two" }) {
+  ///             let greatGrandChildren =
+  ///                 Mirror(reflecting: grandChildren[i1].value).children
+  ///             if let i2 = greatGrandChildren.index(
+  ///                 greatGrandChildren.startIndex,
+  ///                 offsetBy: 3,
+  ///                 limitedBy: greatGrandChildren.endIndex),
+  ///                 i2 != greatGrandChildren.endIndex
+  ///             {
+  ///                 // Success!
+  ///                 result = greatGrandChildren[i2].value
+  ///             }
   ///         }
-  ///       }
   ///     }
   ///
-  /// As you can see, complexity for each element of the argument list
-  /// depends on the argument type and capabilities of the collection
-  /// used to initialize the corresponding subject's parent's mirror.
-  /// Each `String` argument results in a linear search.  In short,
-  /// this function is suitable for exploring the structure of a
-  /// `Mirror` in a REPL or playground, but don't expect it to be
-  /// efficient.
+  /// This function is suitable for exploring the structure of a mirror in a
+  /// REPL or playground, but is not intended to be efficient. The efficiency
+  /// of finding each element in the argument list depends on the argument
+  /// type and the capabilities of the each level of the mirror's `children`
+  /// collections. Each string argument requires a linear search, and unless
+  /// the underlying collection supports random-access traversal, each integer
+  /// argument also requires a linear operation.
+  ///
+  /// - Parameters:
+  ///   - first: The first mirror path component to access.
+  ///   - rest: Any remaining mirror path components.
+  /// - Returns: The descendant of this mirror specified by the given mirror
+  ///   path components if such a descendant exists; otherwise, `nil`.
   @_inlineable // FIXME(sil-serialize-all)
   public func descendant(
     _ first: MirrorPath, _ rest: MirrorPath...
@@ -698,19 +731,20 @@
 }
 
 extension PlaygroundQuickLook {
-  /// Initialize for the given `subject`.
+  /// Creates a new Quick Look for the given instance.
   ///
   /// If the dynamic type of `subject` conforms to
-  /// `CustomPlaygroundQuickLookable`, returns the result of calling
-  /// its `customPlaygroundQuickLook` property.  Otherwise, returns
-  /// a `PlaygroundQuickLook` synthesized for `subject` by the
-  /// language.  Note that in some cases the result may be
-  /// `.Text(String(reflecting: subject))`.
+  /// `CustomPlaygroundQuickLookable`, the result is found by calling its
+  /// `customPlaygroundQuickLook` property. Otherwise, the result is
+  /// synthesized by the language. In some cases, the synthesized result may
+  /// be `.text(String(reflecting: subject))`.
   ///
-  /// - Note: If the dynamic type of `subject` has value semantics,
-  ///   subsequent mutations of `subject` will not observable in
-  ///   `Mirror`.  In general, though, the observability of such
-  ///   mutations is unspecified.
+  /// - Note: If the dynamic type of `subject` has value semantics, subsequent
+  ///   mutations of `subject` will not observable in the Quick Look. In
+  ///   general, though, the observability of such mutations is unspecified.
+  ///
+  /// - Parameter subject: The instance to represent with the resulting Quick
+  ///   Look.
   @_inlineable // FIXME(sil-serialize-all)
   public init(reflecting subject: Any) {
     if let customized = subject as? CustomPlaygroundQuickLookable {
diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift
index 72ce864..459b249 100644
--- a/stdlib/public/core/Optional.swift
+++ b/stdlib/public/core/Optional.swift
@@ -313,98 +313,100 @@
     line: UInt(_line))
 }
 
-/// Returns a Boolean value indicating whether two optional instances are
-/// equal.
-///
-/// Use this equal-to operator (`==`) to compare any two optional instances of
-/// a type that conforms to the `Equatable` protocol. The comparison returns
-/// `true` if both arguments are `nil` or if the two arguments wrap values
-/// that are equal. Conversely, the comparison returns `false` if only one of
-/// the arguments is `nil` or if the two arguments wrap values that are not
-/// equal.
-///
-///     let group1 = [1, 2, 3, 4, 5]
-///     let group2 = [1, 3, 5, 7, 9]
-///     if group1.first == group2.first {
-///         print("The two groups start the same.")
-///     }
-///     // Prints "The two groups start the same."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In the following example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-///     let numberToFind: Int = 23
-///     let numberFromString: Int? = Int("23")      // Optional(23)
-///     if numberToFind == numberFromString {
-///         print("It's a match!")
-///     }
-///     // Prints "It's a match!"
-///
-/// An instance that is expressed as a literal can also be used with this
-/// operator. In the next example, an integer literal is compared with the
-/// optional integer `numberFromString`. The literal `23` is inferred as an
-/// `Int` instance and then wrapped as an optional before the comparison is
-/// performed.
-///
-///     if 23 == numberFromString {
-///         print("It's a match!")
-///     }
-///     // Prints "It's a match!"
-///
-/// - Parameters:
-///   - lhs: An optional value to compare.
-///   - rhs: Another optional value to compare.
-@_inlineable
-public func == <T: Equatable>(lhs: T?, rhs: T?) -> Bool {
-  switch (lhs, rhs) {
-  case let (l?, r?):
-    return l == r
-  case (nil, nil):
-    return true
-  default:
-    return false
+extension Optional : Equatable where Wrapped : Equatable {
+  /// Returns a Boolean value indicating whether two optional instances are
+  /// equal.
+  ///
+  /// Use this equal-to operator (`==`) to compare any two optional instances of
+  /// a type that conforms to the `Equatable` protocol. The comparison returns
+  /// `true` if both arguments are `nil` or if the two arguments wrap values
+  /// that are equal. Conversely, the comparison returns `false` if only one of
+  /// the arguments is `nil` or if the two arguments wrap values that are not
+  /// equal.
+  ///
+  ///     let group1 = [1, 2, 3, 4, 5]
+  ///     let group2 = [1, 3, 5, 7, 9]
+  ///     if group1.first == group2.first {
+  ///         print("The two groups start the same.")
+  ///     }
+  ///     // Prints "The two groups start the same."
+  ///
+  /// You can also use this operator to compare a non-optional value to an
+  /// optional that wraps the same type. The non-optional value is wrapped as an
+  /// optional before the comparison is made. In the following example, the
+  /// `numberToMatch` constant is wrapped as an optional before comparing to the
+  /// optional `numberFromString`:
+  ///
+  ///     let numberToFind: Int = 23
+  ///     let numberFromString: Int? = Int("23")      // Optional(23)
+  ///     if numberToFind == numberFromString {
+  ///         print("It's a match!")
+  ///     }
+  ///     // Prints "It's a match!"
+  ///
+  /// An instance that is expressed as a literal can also be used with this
+  /// operator. In the next example, an integer literal is compared with the
+  /// optional integer `numberFromString`. The literal `23` is inferred as an
+  /// `Int` instance and then wrapped as an optional before the comparison is
+  /// performed.
+  ///
+  ///     if 23 == numberFromString {
+  ///         print("It's a match!")
+  ///     }
+  ///     // Prints "It's a match!"
+  ///
+  /// - Parameters:
+  ///   - lhs: An optional value to compare.
+  ///   - rhs: Another optional value to compare.
+  @_inlineable
+  public static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+    switch (lhs, rhs) {
+    case let (l?, r?):
+      return l == r
+    case (nil, nil):
+      return true
+    default:
+      return false
+    }
   }
-}
-
-/// Returns a Boolean value indicating whether two optional instances are not
-/// equal.
-///
-/// Use this not-equal-to operator (`!=`) to compare any two optional instances
-/// of a type that conforms to the `Equatable` protocol. The comparison
-/// returns `true` if only one of the arguments is `nil` or if the two
-/// arguments wrap values that are not equal. The comparison returns `false`
-/// if both arguments are `nil` or if the two arguments wrap values that are
-/// equal.
-///
-///     let group1 = [2, 4, 6, 8, 10]
-///     let group2 = [1, 3, 5, 7, 9]
-///     if group1.first != group2.first {
-///         print("The two groups start differently.")
-///     }
-///     // Prints "The two groups start differently."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In this example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-///     let numberToFind: Int = 23
-///     let numberFromString: Int? = Int("not-a-number")      // nil
-///     if numberToFind != numberFromString {
-///         print("No match.")
-///     }
-///     // Prints "No match."
-///
-/// - Parameters:
-///   - lhs: An optional value to compare.
-///   - rhs: Another optional value to compare.
-@_inlineable
-public func != <T : Equatable>(lhs: T?, rhs: T?) -> Bool {
-  return !(lhs == rhs)
+  
+  /// Returns a Boolean value indicating whether two optional instances are not
+  /// equal.
+  ///
+  /// Use this not-equal-to operator (`!=`) to compare any two optional instances
+  /// of a type that conforms to the `Equatable` protocol. The comparison
+  /// returns `true` if only one of the arguments is `nil` or if the two
+  /// arguments wrap values that are not equal. The comparison returns `false`
+  /// if both arguments are `nil` or if the two arguments wrap values that are
+  /// equal.
+  ///
+  ///     let group1 = [2, 4, 6, 8, 10]
+  ///     let group2 = [1, 3, 5, 7, 9]
+  ///     if group1.first != group2.first {
+  ///         print("The two groups start differently.")
+  ///     }
+  ///     // Prints "The two groups start differently."
+  ///
+  /// You can also use this operator to compare a non-optional value to an
+  /// optional that wraps the same type. The non-optional value is wrapped as an
+  /// optional before the comparison is made. In this example, the
+  /// `numberToMatch` constant is wrapped as an optional before comparing to the
+  /// optional `numberFromString`:
+  ///
+  ///     let numberToFind: Int = 23
+  ///     let numberFromString: Int? = Int("not-a-number")      // nil
+  ///     if numberToFind != numberFromString {
+  ///         print("No match.")
+  ///     }
+  ///     // Prints "No match."
+  ///
+  /// - Parameters:
+  ///   - lhs: An optional value to compare.
+  ///   - rhs: Another optional value to compare.
+  @_inlineable
+  public static func !=(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+    return !(lhs == rhs)
+  }
 }
 
 // Enable pattern matching against the nil literal, even if the element type
@@ -418,175 +420,177 @@
   }
 }
 
-/// Returns a Boolean value indicating whether an argument matches `nil`.
-///
-/// You can use the pattern-matching operator (`~=`) to test whether an
-/// optional instance is `nil` even when the wrapped value's type does not
-/// conform to the `Equatable` protocol. The pattern-matching operator is used
-/// internally in `case` statements for pattern matching.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type, and then uses a `switch`
-/// statement to determine whether the stream is `nil` or has a configured
-/// value. When evaluating the `nil` case of the `switch` statement, this
-/// operator is called behind the scenes.
-///
-///     var stream: DataStream? = nil
-///     switch stream {
-///     case nil:
-///         print("No data stream is configured.")
-///     case let x?:
-///         print("The data stream has \(x.availableBytes) bytes available.")
-///     }
-///     // Prints "No data stream is configured."
-///
-/// - Note: To test whether an instance is `nil` in an `if` statement, use the
-///   equal-to operator (`==`) instead of the pattern-matching operator. The
-///   pattern-matching operator is primarily intended to enable `case`
-///   statement pattern matching.
-///
-/// - Parameters:
-///   - lhs: A `nil` literal.
-///   - rhs: A value to match against `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func ~= <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
-  switch rhs {
-  case .some(_):
-    return false
-  case .none:
-    return true
+extension Optional {
+  /// Returns a Boolean value indicating whether an argument matches `nil`.
+  ///
+  /// You can use the pattern-matching operator (`~=`) to test whether an
+  /// optional instance is `nil` even when the wrapped value's type does not
+  /// conform to the `Equatable` protocol. The pattern-matching operator is used
+  /// internally in `case` statements for pattern matching.
+  ///
+  /// The following example declares the `stream` variable as an optional
+  /// instance of a hypothetical `DataStream` type, and then uses a `switch`
+  /// statement to determine whether the stream is `nil` or has a configured
+  /// value. When evaluating the `nil` case of the `switch` statement, this
+  /// operator is called behind the scenes.
+  ///
+  ///     var stream: DataStream? = nil
+  ///     switch stream {
+  ///     case nil:
+  ///         print("No data stream is configured.")
+  ///     case let x?:
+  ///         print("The data stream has \(x.availableBytes) bytes available.")
+  ///     }
+  ///     // Prints "No data stream is configured."
+  ///
+  /// - Note: To test whether an instance is `nil` in an `if` statement, use the
+  ///   equal-to operator (`==`) instead of the pattern-matching operator. The
+  ///   pattern-matching operator is primarily intended to enable `case`
+  ///   statement pattern matching.
+  ///
+  /// - Parameters:
+  ///   - lhs: A `nil` literal.
+  ///   - rhs: A value to match against `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  static public func ~=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+    switch rhs {
+    case .some(_):
+      return false
+    case .none:
+      return true
+    }
   }
-}
 
-// Enable equality comparisons against the nil literal, even if the
-// element type isn't equatable
+  // Enable equality comparisons against the nil literal, even if the
+  // element type isn't equatable
 
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-///     var stream: DataStream? = nil
-///     if stream == nil {
-///         print("No data stream is configured.")
-///     }
-///     // Prints "No data stream is configured."
-///
-/// - Parameters:
-///   - lhs: A value to compare to `nil`.
-///   - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
-  switch lhs {
-  case .some(_):
-    return false
-  case .none:
-    return true
+  /// Returns a Boolean value indicating whether the left-hand-side argument is
+  /// `nil`.
+  ///
+  /// You can use this equal-to operator (`==`) to test whether an optional
+  /// instance is `nil` even when the wrapped value's type does not conform to
+  /// the `Equatable` protocol.
+  ///
+  /// The following example declares the `stream` variable as an optional
+  /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+  /// an `Equatable` type, this operator allows checking whether `stream` is
+  /// `nil`.
+  ///
+  ///     var stream: DataStream? = nil
+  ///     if stream == nil {
+  ///         print("No data stream is configured.")
+  ///     }
+  ///     // Prints "No data stream is configured."
+  ///
+  /// - Parameters:
+  ///   - lhs: A value to compare to `nil`.
+  ///   - rhs: A `nil` literal.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  static public func ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+    switch lhs {
+    case .some(_):
+      return false
+    case .none:
+      return true
+    }
   }
-}
 
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-///     var stream: DataStream? = fetchDataStream()
-///     if stream != nil {
-///         print("The data stream has been configured.")
-///     }
-///     // Prints "The data stream has been configured."
-///
-/// - Parameters:
-///   - lhs: A value to compare to `nil`.
-///   - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
-  switch lhs {
-  case .some(_):
-    return true
-  case .none:
-    return false
+  /// Returns a Boolean value indicating whether the left-hand-side argument is
+  /// not `nil`.
+  ///
+  /// You can use this not-equal-to operator (`!=`) to test whether an optional
+  /// instance is not `nil` even when the wrapped value's type does not conform
+  /// to the `Equatable` protocol.
+  ///
+  /// The following example declares the `stream` variable as an optional
+  /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+  /// an `Equatable` type, this operator allows checking whether `stream` wraps
+  /// a value and is therefore not `nil`.
+  ///
+  ///     var stream: DataStream? = fetchDataStream()
+  ///     if stream != nil {
+  ///         print("The data stream has been configured.")
+  ///     }
+  ///     // Prints "The data stream has been configured."
+  ///
+  /// - Parameters:
+  ///   - lhs: A value to compare to `nil`.
+  ///   - rhs: A `nil` literal.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  static public func !=(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+    switch lhs {
+    case .some(_):
+      return true
+    case .none:
+      return false
+    }
   }
-}
 
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-///     var stream: DataStream? = nil
-///     if nil == stream {
-///         print("No data stream is configured.")
-///     }
-///     // Prints "No data stream is configured."
-///
-/// - Parameters:
-///   - lhs: A `nil` literal.
-///   - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
-  switch rhs {
-  case .some(_):
-    return false
-  case .none:
-    return true
+  /// Returns a Boolean value indicating whether the right-hand-side argument is
+  /// `nil`.
+  ///
+  /// You can use this equal-to operator (`==`) to test whether an optional
+  /// instance is `nil` even when the wrapped value's type does not conform to
+  /// the `Equatable` protocol.
+  ///
+  /// The following example declares the `stream` variable as an optional
+  /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+  /// an `Equatable` type, this operator allows checking whether `stream` is
+  /// `nil`.
+  ///
+  ///     var stream: DataStream? = nil
+  ///     if nil == stream {
+  ///         print("No data stream is configured.")
+  ///     }
+  ///     // Prints "No data stream is configured."
+  ///
+  /// - Parameters:
+  ///   - lhs: A `nil` literal.
+  ///   - rhs: A value to compare to `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  static public func ==(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+    switch rhs {
+    case .some(_):
+      return false
+    case .none:
+      return true
+    }
   }
-}
 
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-///     var stream: DataStream? = fetchDataStream()
-///     if nil != stream {
-///         print("The data stream has been configured.")
-///     }
-///     // Prints "The data stream has been configured."
-///
-/// - Parameters:
-///   - lhs: A `nil` literal.
-///   - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
-  switch rhs {
-  case .some(_):
-    return true
-  case .none:
-    return false
+  /// Returns a Boolean value indicating whether the right-hand-side argument is
+  /// not `nil`.
+  ///
+  /// You can use this not-equal-to operator (`!=`) to test whether an optional
+  /// instance is not `nil` even when the wrapped value's type does not conform
+  /// to the `Equatable` protocol.
+  ///
+  /// The following example declares the `stream` variable as an optional
+  /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+  /// an `Equatable` type, this operator allows checking whether `stream` wraps
+  /// a value and is therefore not `nil`.
+  ///
+  ///     var stream: DataStream? = fetchDataStream()
+  ///     if nil != stream {
+  ///         print("The data stream has been configured.")
+  ///     }
+  ///     // Prints "The data stream has been configured."
+  ///
+  /// - Parameters:
+  ///   - lhs: A `nil` literal.
+  ///   - rhs: A value to compare to `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  static public func !=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+    switch rhs {
+    case .some(_):
+      return true
+    case .none:
+      return false
+    }
   }
 }
 
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index e4649b7..8128f8c 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -15,8 +15,8 @@
 //===----------------------------------------------------------------------===//
 // Standardized uninhabited type
 //===----------------------------------------------------------------------===//
-/// The return type of functions that do not return normally; a type with no
-/// values.
+/// The return type of functions that do not return normally, that is, a type
+/// with no values.
 ///
 /// Use `Never` as the return type when declaring a closure, function, or
 /// method that unconditionally throws an error, traps, or otherwise does
@@ -31,16 +31,16 @@
 //===----------------------------------------------------------------------===//
 // Standardized aliases
 //===----------------------------------------------------------------------===//
-/// The return type of functions that don't explicitly specify a return type;
-/// an empty tuple (i.e., `()`).
+/// The return type of functions that don't explicitly specify a return type,
+/// that is, an empty tuple `()`.
 ///
 /// When declaring a function or method, you don't need to specify a return
 /// type if no value will be returned. However, the type of a function,
 /// method, or closure always includes a return type, which is `Void` if
 /// otherwise unspecified.
 ///
-/// Use `Void` or an empty tuple as the return type when declaring a
-/// closure, function, or method that doesn't return a value.
+/// Use `Void` or an empty tuple as the return type when declaring a closure,
+/// function, or method that doesn't return a value.
 ///
 ///     // No return type declared:
 ///     func logMessage(_ s: String) {
diff --git a/stdlib/public/core/Sort.swift.gyb b/stdlib/public/core/Sort.swift.gyb
index b59c8cb..f7992d1 100644
--- a/stdlib/public/core/Sort.swift.gyb
+++ b/stdlib/public/core/Sort.swift.gyb
@@ -406,9 +406,15 @@
 % end
 // for p in preds
 
-/// Exchange the values of `a` and `b`.
+/// Exchanges the values of the two arguments.
 ///
-/// - Precondition: `a` and `b` do not alias each other.
+/// The two arguments must not alias each other. To swap two elements of a
+/// mutable collection, use the `swapAt(_:_:)` method of that collection
+/// instead of this function.
+///
+/// - Parameters:
+///   - a: The first value to swap.
+///   - b: The second value to swap.
 @_inlineable
 public func swap<T>(_ a: inout T, _ b: inout T) {
   // Semantically equivalent to (a, b) = (b, a).
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index 74792b6..40e2298 100644
--- a/stdlib/public/core/Stride.swift.gyb
+++ b/stdlib/public/core/Stride.swift.gyb
@@ -274,8 +274,126 @@
   public var customMirror: Mirror {
     return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
   }
+
+  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+  // here until a proper Collection conformance is possible
+  @_inlineable
+  public var underestimatedCount: Int {
+    var it = self.makeIterator()
+    var count = 0
+    while it.next() != nil {
+      count += 1
+    }
+    return count
+  }
 }
 
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideTo type
+% for Self, ElementConstraint, Where in [
+%   ('IntegerStrideToCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+%   ('FloatingPointStrideToCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+%   ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+  Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideTo struct definition                       //
+//===----------------------------------------------------------------------===//
+  @_inlineable
+  public func makeIterator() -> StrideToIterator<Element> {
+    return StrideToIterator(_start: _start, end: _end, stride: _stride)
+  }
+
+  @_inlineable
+  public func _customContainsEquatableElement(
+    _ element: Element
+  ) -> Bool? {
+    if element < _start || _end <= element {
+      return false
+    }
+    return nil
+  }
+
+  @_inlineable
+  @_versioned
+  internal init(_start: Element, end: Element, stride: Element.Stride) {
+    _precondition(stride != 0, "Stride size must not be zero")
+    // At start, striding away from end is allowed; it just makes for an
+    // already-empty Sequence.
+    self._start = _start
+    self._end = end
+    self._stride = stride
+  }
+
+  @_versioned
+  internal let _start: Element
+
+  @_versioned
+  internal let _end: Element
+
+  @_versioned
+  internal let _stride: Element.Stride
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public var customMirror: Mirror {
+    return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
+  }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+  // RandomAccessCollection conformance
+  public typealias Index = Int
+  public typealias SubSequence = RandomAccessSlice<${Self}>
+  public typealias Indices = CountableRange<Int>
+
+  public var startIndex: Index { return 0 }
+  public var endIndex: Index { return count }
+
+  public var count: Int {
+    let (start, end, stride) =
+      (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+%   if ElementIsInteger:
+    return Int((start.distance(to: end) - 1) / stride) + 1
+%   else:
+    let nonExactCount = (start.distance(to: end)) / stride
+    return Int(nonExactCount.rounded(.toNearestOrAwayFromZero))
+%   end
+  }
+
+  public subscript(position: Index) -> Element {
+    _failEarlyRangeCheck(position, bounds: startIndex ..< endIndex)
+    return _indexToElement(position)
+  }
+
+  public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+    _failEarlyRangeCheck(bounds, bounds: startIndex ..< endIndex)
+    return RandomAccessSlice(base: self, bounds: bounds)
+  }
+
+  public func index(after i: Index) -> Index {
+    _failEarlyRangeCheck(i, bounds: startIndex-1 ..< endIndex)
+    return i+1
+  }
+
+  public func index(before i: Index) -> Index {
+    _failEarlyRangeCheck(i, bounds: startIndex+1 ... endIndex)
+    return i-1
+  }
+
+  @inline(__always)
+  internal func _indexToElement(_ i: Index) -> Element {
+    return _start.advanced(by: Element.Stride(i) * _stride)
+  }
+}
+
+% end
+
 /// Returns the sequence of values (`self`, `self + stride`, `self +
 /// 2 * stride`, ... *last*) where *last* is the last value in the
 /// progression that is less than `end`.
@@ -388,8 +506,148 @@
     return Mirror(self,
       children: ["from": _start, "through": _end, "by": _stride])
   }
+
+  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+  // here until a proper Collection conformance is possible
+  @_inlineable
+  public var underestimatedCount: Int {
+    var it = self.makeIterator()
+    var count = 0
+    while it.next() != nil {
+      count += 1
+    }
+    return count
+  }
 }
 
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideThrough type
+% for Self, ElementConstraint, Where in [
+%   ('IntegerStrideThroughCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+%   ('FloatingPointStrideThroughCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+%   ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+  Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideThrough struct definition                  //
+//===----------------------------------------------------------------------===//
+  /// Returns an iterator over the elements of this sequence.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable
+  public func makeIterator() -> StrideThroughIterator<Element> {
+    return StrideThroughIterator(_start: _start, end: _end, stride: _stride)
+  }
+
+  @_inlineable
+  public func _customContainsEquatableElement(
+    _ element: Element
+  ) -> Bool? {
+    if element < _start || _end < element {
+      return false
+    }
+    return nil
+  }
+
+  @_inlineable
+  @_versioned
+  internal init(_start: Element, end: Element, stride: Element.Stride) {
+    _precondition(stride != 0, "Stride size must not be zero")
+    self._start = _start
+    self._end = end
+    self._stride = stride
+  }
+
+  @_versioned
+  internal let _start: Element
+  @_versioned
+  internal let _end: Element
+  @_versioned
+  internal let _stride: Element.Stride
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public var customMirror: Mirror {
+    return Mirror(self,
+      children: ["from": _start, "through": _end, "by": _stride])
+  }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+  // RandomAccessCollection conformance
+  public typealias Index = ClosedRangeIndex<Int>
+  public typealias IndexDistance = Int
+  public typealias SubSequence = RandomAccessSlice<${Self}>
+
+  @_inlineable
+  public var startIndex: Index { return ClosedRangeIndex(0) }
+  @_inlineable
+  public var endIndex: Index { return ClosedRangeIndex() }
+
+  @_inlineable
+  public var count: Int {
+    let (start, end, stride) =
+      (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+%   if ElementIsInteger:
+    return Int(start.distance(to: end) / stride) + 1
+%   else:
+    let nonExactCount = start.distance(to: end) / stride
+    return Int(nonExactCount.rounded(.toNearestOrAwayFromZero)) + 1
+%   end
+  }
+
+  public subscript(position: Index) -> Element {
+    let offset = Element.Stride(position._dereferenced) * _stride
+    return _start.advanced(by: offset)
+  }
+
+  public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+    return RandomAccessSlice(base: self, bounds: bounds)
+  }
+
+  @_inlineable
+  public func index(before i: Index) -> Index {
+    switch i._value {
+    case .inRange(let n):
+      _precondition(n > 0, "Incrementing past start index")
+      return ClosedRangeIndex(n - 1)
+    case .pastEnd:
+      _precondition(_end >= _start, "Incrementing past start index")
+      return ClosedRangeIndex(count - 1)
+    }
+  }
+
+  @_inlineable
+  public func index(after i: Index) -> Index {
+    switch i._value {
+    case .inRange(let n):
+      return n == (count - 1)
+        ? ClosedRangeIndex()
+        : ClosedRangeIndex(n + 1)
+    case .pastEnd:
+      _preconditionFailure("Incrementing past end index")
+    }
+  }
+
+  // FIXME(ABI)#175 (Type checker)
+  @_inlineable
+  public // WORKAROUND: needed because of rdar://25584401
+  var indices: DefaultRandomAccessIndices<${Self}> {
+    return DefaultRandomAccessIndices(
+      _elements: self,
+      startIndex: self.startIndex,
+      endIndex: self.endIndex)
+  }
+
+}
+
+% end
+
 /// Returns the sequence of values (`self`, `self + stride`, `self +
 /// 2 * stride`, ... *last*) where *last* is the last value in the
 /// progression less than or equal to `end`.
@@ -401,3 +659,4 @@
 ) -> StrideThrough<T> {
   return StrideThrough(_start: start, end: end, stride: stride)
 }
+
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 7552225..7339112 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -48,7 +48,7 @@
   /// encoding.
   ///
   /// - Parameters:
-  ///   - codeUnits: A collection of code units encoded in the ecoding
+  ///   - codeUnits: A collection of code units encoded in the encoding
   ///     specified in `sourceEncoding`.
   ///   - sourceEncoding: The encoding in which `codeUnits` should be
   ///     interpreted.
@@ -280,7 +280,7 @@
   /// encoding.
   ///
   /// - Parameters:
-  ///   - codeUnits: A collection of code units encoded in the ecoding
+  ///   - codeUnits: A collection of code units encoded in the encoding
   ///     specified in `sourceEncoding`.
   ///   - sourceEncoding: The encoding in which `codeUnits` should be
   ///     interpreted.
@@ -673,6 +673,12 @@
 @_fixed_layout
 public struct String {
   /// Creates an empty string.
+  ///
+  /// Using this initializer is equivalent to initializing a string with an
+  /// empty string literal.
+  ///
+  ///     let empty = ""
+  ///     let alsoEmpty = String()
   @_inlineable // FIXME(sil-serialize-all)
   public init() {
     _core = _StringCore()
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 6be2abd..5af0bcd 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -29,6 +29,11 @@
   ///     let zeroes = String(repeating: "0" as Character, count: 10)
   ///     print(zeroes)
   ///     // Prints "0000000000"
+  ///
+  /// - Parameters:
+  ///   - repeatedValue: The character to repeat.
+  ///   - count: The number of times to repeat `repeatedValue` in the 
+  ///     resulting string.
   @_inlineable // FIXME(sil-serialize-all)
   public init(repeating repeatedValue: Character, count: Int) {
     self.init(repeating: String(repeatedValue), count: count)
@@ -38,6 +43,22 @@
   // that String conforms to Collection:
   // - init<T>(_ value: T) where T : LosslessStringConvertible
   // - init<S>(_ characters: S) where S : Sequence, S.Element == Character
+  
+  /// Creates a new string containing the characters in the given sequence.
+  ///
+  /// You can use this initializer to create a new string from the result of
+  /// one or more collection operations on a string's characters. For example:
+  ///
+  ///     let str = "The rain in Spain stays mainly in the plain."
+  ///
+  ///     let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
+  ///     let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
+  ///
+  ///     print(disemvoweled)
+  ///     // Prints "Th rn n Spn stys mnly n th pln."
+  ///
+  /// - Parameter other: A string instance or another sequence of 
+  ///   characters.
   @_inlineable // FIXME(sil-serialize-all)
   public init<S : Sequence & LosslessStringConvertible>(_ other: S)
   where S.Element == Character {
@@ -171,14 +192,16 @@
 
   /// Accesses the character at the given position.
   ///
-  /// Indices for a subscripting a string are shared with the string's
-  /// `characters` view. For example:
+  /// You can use the same indices for subscripting a string and its substring.
+  /// For example, this code finds the first letter after the first space:
   ///
-  ///     let greeting = "Hello, friend!"
-  ///     if let i = greeting.characters.index(where: { $0 >= "A" && $0 <= "Z" }) {
-  ///         print("First capital letter: \(greeting[i])")
+  ///     let str = "Greetings, friend! How are you?"
+  ///     let firstSpace = str.index(of: " ") ?? str.endIndex
+  ///     let substr = str[firstSpace...]
+  ///     if let nextCapital = substr.index(where: { $0 >= "A" && $0 <= "Z" }) {
+  ///         print("Capital after a space: \(str[nextCapital])")
   ///     }
-  ///     // Prints "First capital letter: H"
+  ///     // Prints "Capital after a space: H"
   ///
   /// - Parameter i: A valid index of the string. `i` must be less than the
   ///   string's end index.
@@ -190,17 +213,18 @@
   /// Creates a new string containing the characters in the given sequence.
   ///
   /// You can use this initializer to create a new string from the result of
-  /// one or more operations on a string's `characters` view. For example:
+  /// one or more collection operations on a string's characters. For example:
   ///
   ///     let str = "The rain in Spain stays mainly in the plain."
   ///
   ///     let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
-  ///     let disemvoweled = String(str.characters.lazy.filter { !vowels.contains($0) })
+  ///     let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
   ///
   ///     print(disemvoweled)
   ///     // Prints "Th rn n Spn stys mnly n th pln."
   ///
-  /// - Parameter characters: A sequence of characters.
+  /// - Parameter characters: A string instance or another sequence of 
+  ///   characters.
   @_inlineable // FIXME(sil-serialize-all)
   public init<S : Sequence>(_ characters: S)
     where S.Iterator.Element == Character {
@@ -326,7 +350,7 @@
   /// removes the hyphen from the middle of a string.
   ///
   ///     var nonempty = "non-empty"
-  ///     if let i = nonempty.characters.index(of: "-") {
+  ///     if let i = nonempty.index(of: "-") {
   ///         nonempty.remove(at: i)
   ///     }
   ///     print(nonempty)
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 4c6208d..8c0f007 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -205,7 +205,7 @@
   /// encoding.
   ///
   /// - Parameters:
-  ///   - codeUnits: A collection of code units encoded in the ecoding
+  ///   - codeUnits: A collection of code units encoded in the encoding
   ///     specified in `sourceEncoding`.
   ///   - sourceEncoding: The encoding in which `codeUnits` should be
   ///     interpreted.
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index 9b29437..0541c78 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -42,7 +42,7 @@
 % for mutable in (True, False):
 %  Self = 'UnsafeMutableBufferPointer' if mutable else 'UnsafeBufferPointer'
 %  Mutable = 'Mutable' if mutable else ''
-/// A non-owning collection interface to a buffer of ${Mutable.lower()}
+/// A nonowning collection interface to a buffer of ${Mutable.lower()}
 /// elements stored contiguously in memory.
 ///
 /// You can use an `${Self}` instance in low level operations to eliminate
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index cffeb4f..d80f6be 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -10,28 +10,30 @@
 //
 //===----------------------------------------------------------------------===//
 
-/// Instances of conforming types can be encoded, and appropriately
-/// passed, as elements of a C `va_list`.
+/// A type whose instances can be encoded, and appropriately passed, as
+/// elements of a C `va_list`.
 ///
-/// This protocol is useful in presenting C "varargs" APIs natively in
-/// Swift.  It only works for APIs that have a `va_list` variant, so
-/// for example, it isn't much use if all you have is:
+/// You use this protocol to present a native Swift interface to a C "varargs"
+/// API. For example, a program can import a C API like the one defined here:
 ///
-/// ~~~ c
-/// int c_api(int n, ...)
-/// ~~~
-///
-/// Given a version like this, though,
-///
-/// ~~~ c
+/// ~~~c
 /// int c_api(int, va_list arguments)
 /// ~~~
 ///
-/// you can write:
+/// To create a wrapper for the `c_api` function, write a function that takes
+/// `CVarArg` arguments, and then call the imported C function using the
+/// `withVaList(_:_:)` function:
 ///
 ///     func swiftAPI(_ x: Int, arguments: CVarArg...) -> Int {
-///       return withVaList(arguments) { c_api(x, $0) }
+///         return withVaList(arguments) { c_api(x, $0) }
 ///     }
+///
+/// Swift only imports C variadic functions that use a `va_list` for their
+/// arguments. C functions that use the `...` syntax for variadic arguments
+/// are not imported, and therefore can't be called using `CVarArg` arguments.
+///
+/// - Note: Declaring conformance to the `CVarArg` protocol for types defined
+///   outside the standard library is not supported.
 public protocol CVarArg {
   // Note: the protocol is public, but its requirement is stdlib-private.
   // That's because there are APIs operating on CVarArg instances, but
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 12536a0..175e17f 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -1920,12 +1920,18 @@
     // The result and argument types must match.
     if (srcFn->ResultType != targetFn->ResultType)
       return _fail(src, srcType, targetType, flags);
-    if (srcFn->getNumArguments() != targetFn->getNumArguments())
+    if (srcFn->getNumParameters() != targetFn->getNumParameters())
       return _fail(src, srcType, targetType, flags);
-    for (unsigned i = 0, e = srcFn->getNumArguments(); i < e; ++i)
-      if (srcFn->getArguments()[i] != targetFn->getArguments()[i])
+
+    if (srcFn->hasParameterFlags() != targetFn->hasParameterFlags())
+      return _fail(src, srcType, targetType, flags);
+
+    for (unsigned i = 0, e = srcFn->getNumParameters(); i < e; ++i) {
+      if (srcFn->getParameter(i) != targetFn->getParameter(i) ||
+          srcFn->getParameterFlags(i) != targetFn->getParameterFlags(i))
         return _fail(src, srcType, targetType, flags);
-    
+    }
+
     return _succeed(dest, src, srcType, flags);
   }
   
@@ -3196,7 +3202,7 @@
 const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
   if (const ClassMetadata *classType = theClass->getClassObject())
     if (classHasSuperclass(classType))
-      return swift_getObjCClassMetadata(classType->SuperClass);
+      return getMetadataForClass(classType->SuperClass);
   return nullptr;
 }
 
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 3f2aaa1..379151e 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -319,13 +319,19 @@
     }
     
     std::vector<NodePointer> inputs;
-    for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) {
-      auto arg = func->getArguments()[i];
-      auto input = _swift_buildDemanglingForMetadata(arg.getPointer(), Dem);
-      if (arg.getFlag()) {
+    for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
+      auto param = func->getParameter(i);
+      auto flags = func->getParameterFlags(i);
+      auto input = _swift_buildDemanglingForMetadata(param, Dem);
+
+      if (flags.isInOut()) {
         NodePointer inout = Dem.createNode(Node::Kind::InOut);
         inout->addChild(input, Dem);
         input = inout;
+      } else if (flags.isShared()) {
+        NodePointer shared = Dem.createNode(Node::Kind::Shared);
+        shared->addChild(input, Dem);
+        input = shared;
       }
       inputs.push_back(input);
     }
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index eb74d49..dfcbea4 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -14,22 +14,23 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/MathExtras.h"
-#include "swift/Demangling/Demangler.h"
+#include "swift/Runtime/Metadata.h"
+#include "MetadataCache.h"
 #include "swift/Basic/LLVM.h"
-#include "swift/Basic/Range.h"
 #include "swift/Basic/Lazy.h"
+#include "swift/Basic/Range.h"
+#include "swift/Demangling/Demangler.h"
 #include "swift/Runtime/Casting.h"
 #include "swift/Runtime/HeapObject.h"
-#include "swift/Runtime/Metadata.h"
 #include "swift/Runtime/Mutex.h"
 #include "swift/Strings.h"
-#include "MetadataCache.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
 #include <algorithm>
-#include <condition_variable>
-#include <new>
 #include <cctype>
+#include <condition_variable>
 #include <iostream>
+#include <new>
 #if defined(_WIN32)
 #define WIN32_LEAN_AND_MEAN
 // Avoid defining macro max(), min() which conflict with std::max(), std::min()
@@ -281,8 +282,6 @@
 /// The uniquing structure for ObjC class-wrapper metadata.
 static SimpleGlobalCache<ObjCClassCacheEntry> ObjCClassWrappers;
 
-#endif
-
 const Metadata *
 swift::swift_getObjCClassMetadata(const ClassMetadata *theClass) {
   // Make calls resilient against receiving a null Objective-C class. This can
@@ -295,14 +294,24 @@
     return theClass;
   }
 
-#if SWIFT_OBJC_INTEROP
   return &ObjCClassWrappers.getOrInsert(theClass).first->Data;
-#else
-  fatalError(/* flags = */ 0,
-             "swift_getObjCClassMetadata: no Objective-C interop");
-#endif
 }
 
+const ClassMetadata *
+swift::swift_getObjCClassFromMetadata(const Metadata *theMetadata) {
+  // Unwrap ObjC class wrappers.
+  if (auto wrapper = dyn_cast<ObjCClassWrapperMetadata>(theMetadata)) {
+    return wrapper->Class;
+  }
+
+  // Otherwise, the input should already be a Swift class object.
+  auto theClass = cast<ClassMetadata>(theMetadata);
+  assert(theClass->isTypeMetadata() && !theClass->isArtificialSubclass());
+  return theClass;
+}
+
+#endif
+
 /***************************************************************************/
 /*** Functions *************************************************************/
 /***************************************************************************/
@@ -314,20 +323,34 @@
   FullMetadata<FunctionTypeMetadata> Data;
 
   struct Key {
-    const void * const *FlagsArgsAndResult;
+    const FunctionTypeFlags Flags;
 
-    FunctionTypeFlags getFlags() const {
-      return FunctionTypeFlags::fromIntValue(size_t(FlagsArgsAndResult[0]));
+    const Metadata *const *Parameters;
+    const uint32_t *ParameterFlags;
+    const Metadata *Result;
+
+    Key(FunctionTypeFlags flags,
+        const Metadata *const *params,
+        const uint32_t *paramFlags,
+        const Metadata *result)
+      : Flags(flags), Parameters(params), ParameterFlags(paramFlags),
+        Result(result) {}
+
+    FunctionTypeFlags getFlags() const { return Flags; }
+    const Metadata *getParameter(unsigned index) const {
+      assert(index < Flags.getNumParameters());
+      return Parameters[index];
+    }
+    const Metadata *getResult() const { return Result; }
+
+    const uint32_t *getParameterFlags() const {
+      return ParameterFlags;
     }
 
-    const Metadata *getResult() const {
-      auto opaqueResult = FlagsArgsAndResult[getFlags().getNumArguments() + 1];
-      return reinterpret_cast<const Metadata *>(opaqueResult);
-    }
-
-    const void * const *getArguments() const {
-      return getFlags().getNumArguments() == 0
-              ? nullptr : &FlagsArgsAndResult[1];
+    ::ParameterFlags getParameterFlags(unsigned index) const {
+      assert(index < Flags.getNumParameters());
+      auto flags = Flags.hasParameterFlags() ? ParameterFlags[index] : 0;
+      return ParameterFlags::fromIntValue(flags);
     }
   };
 
@@ -346,23 +369,35 @@
     if (auto result = comparePointers(key.getResult(), Data.ResultType))
       return result;
 
-    for (unsigned i = 0, e = keyFlags.getNumArguments(); i != e; ++i) {
+    for (unsigned i = 0, e = keyFlags.getNumParameters(); i != e; ++i) {
       if (auto result =
-            comparePointers(key.getArguments()[i],
-                            Data.getArguments()[i].getOpaqueValue()))
+              comparePointers(key.getParameter(i), Data.getParameter(i)))
+        return result;
+
+      if (auto result =
+              compareIntegers(key.getParameterFlags(i).getIntValue(),
+                              Data.getParameterFlags(i).getIntValue()))
         return result;
     }
 
     return 0;
   }
-
   static size_t getExtraAllocationSize(Key key) {
-    return key.getFlags().getNumArguments()
-         * sizeof(FunctionTypeMetadata::Argument);
+    return getExtraAllocationSize(key.Flags);
   }
+
   size_t getExtraAllocationSize() const {
-    return Data.Flags.getNumArguments()
-         * sizeof(FunctionTypeMetadata::Argument);
+    return getExtraAllocationSize(Data.Flags);
+  }
+
+  static size_t getExtraAllocationSize(const FunctionTypeFlags flags) {
+    const auto numParams = flags.getNumParameters();
+    auto size = numParams * sizeof(FunctionTypeMetadata::Parameter);
+    if (flags.hasParameterFlags())
+      size += numParams * sizeof(uint32_t);
+
+    const auto alignment = sizeof(void *);
+    return (size + alignment - 1) & ~(alignment - 1);
   }
 };
 
@@ -373,53 +408,101 @@
 
 const FunctionTypeMetadata *
 swift::swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
-                                      const void *arg0,
+                                      const Metadata *arg0,
                                       const Metadata *result) {
-  assert(flags.getNumArguments() == 1
+  assert(flags.getNumParameters() == 1
          && "wrong number of arguments in function metadata flags?!");
-  const void *flagsArgsAndResult[] = {
-    reinterpret_cast<const void*>(flags.getIntValue()),
-    arg0,
-    static_cast<const void *>(result)                      
-  };                                                       
-  return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}                                                          
-const FunctionTypeMetadata *                               
-swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
-                                      const void *arg0,
-                                      const void *arg1,
-                                      const Metadata *result) {
-  assert(flags.getNumArguments() == 2
-         && "wrong number of arguments in function metadata flags?!");
-  const void *flagsArgsAndResult[] = {
-    reinterpret_cast<const void*>(flags.getIntValue()),
-    arg0,
-    arg1,                                                  
-    static_cast<const void *>(result)                      
-  };                                                       
-  return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}                                                          
-const FunctionTypeMetadata *                               
-swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
-                                      const void *arg0,
-                                      const void *arg1,
-                                      const void *arg2,
-                                      const Metadata *result) {
-  assert(flags.getNumArguments() == 3
-         && "wrong number of arguments in function metadata flags?!");
-  const void *flagsArgsAndResult[] = {
-    reinterpret_cast<const void*>(flags.getIntValue()),
-    arg0,                                                  
-    arg1,                                                  
-    arg2,                                                  
-    static_cast<const void *>(result)                      
-  };                                                       
-  return swift_getFunctionTypeMetadata(flagsArgsAndResult);
+  const Metadata *parameters[] = { arg0 };
+  return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
 }
 
 const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]) {
-  FunctionCacheEntry::Key key = { flagsArgsAndResult };
+swift::swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+                                               const Metadata *arg0,
+                                               ParameterFlags flags0,
+                                               const Metadata *result) {
+  assert(flags.getNumParameters() == 1
+         && "wrong number of arguments in function metadata flags?!");
+  const Metadata *parameters[] = { arg0 };
+  const uint32_t parameterFlags[] = { flags0.getIntValue() };
+  return swift_getFunctionTypeMetadata(flags,
+                                       parameters,
+                                       parameterFlags,
+                                       result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
+                                      const Metadata *arg0,
+                                      const Metadata *arg1,
+                                      const Metadata *result) {
+  assert(flags.getNumParameters() == 2
+         && "wrong number of arguments in function metadata flags?!");
+  const Metadata *parameters[] = { arg0, arg1 };
+  return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+                                               const Metadata *arg0,
+                                               ParameterFlags flags0,
+                                               const Metadata *arg1,
+                                               ParameterFlags flags1,
+                                               const Metadata *result) {
+  assert(flags.getNumParameters() == 2
+         && "wrong number of arguments in function metadata flags?!");
+  const Metadata *parameters[] = { arg0, arg1 };
+  const uint32_t parameterFlags[] = {
+    flags0.getIntValue(),
+    flags1.getIntValue()
+  };
+  return swift_getFunctionTypeMetadata(flags,
+                                       parameters,
+                                       parameterFlags,
+                                       result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
+                                      const Metadata *arg0,
+                                      const Metadata *arg1,
+                                      const Metadata *arg2,
+                                      const Metadata *result) {
+  assert(flags.getNumParameters() == 3
+         && "wrong number of arguments in function metadata flags?!");
+  const Metadata *parameters[] = { arg0, arg1, arg2 };
+  return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3WithFlags(FunctionTypeFlags flags,
+                                               const Metadata *arg0,
+                                               ParameterFlags flags0,
+                                               const Metadata *arg1,
+                                               ParameterFlags flags1,
+                                               const Metadata *arg2,
+                                               ParameterFlags flags2,
+                                               const Metadata *result) {
+  assert(flags.getNumParameters() == 3
+         && "wrong number of arguments in function metadata flags?!");
+  const Metadata *parameters[] = { arg0, arg1, arg2 };
+  const uint32_t parameterFlags[] = {
+    flags0.getIntValue(),
+    flags1.getIntValue(),
+    flags2.getIntValue()
+  };
+  return swift_getFunctionTypeMetadata(flags,
+                                       parameters,
+                                       parameterFlags,
+                                       result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+                                     const Metadata *const *parameters,
+                                     const uint32_t *parameterFlags,
+                                     const Metadata *result) {
+  FunctionCacheEntry::Key key = { flags, parameters, parameterFlags, result };
   return &FunctionTypes.getOrInsert(key).first->Data;
 }
 
@@ -450,16 +533,16 @@
     break;
   }
 
-  unsigned numArguments = flags.getNumArguments();
+  unsigned numParameters = flags.getNumParameters();
 
   Data.setKind(MetadataKind::Function);
   Data.Flags = flags;
   Data.ResultType = key.getResult();
 
-  for (size_t i = 0; i < numArguments; ++i) {
-    auto opaqueArg = key.getArguments()[i];
-    auto arg = FunctionTypeMetadata::Argument::getFromOpaqueValue(opaqueArg);
-    Data.getArguments()[i] = arg;
+  for (unsigned i = 0; i < numParameters; ++i) {
+    Data.getParameters()[i] = key.getParameter(i);
+    if (flags.hasParameterFlags())
+      Data.getParameterFlags()[i] = key.getParameterFlags(i).getIntValue();
   }
 }
 
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index b13716b..f092b76 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -137,8 +137,9 @@
   }
   case TypeMetadataRecordKind::UniqueDirectClass:
     if (auto *ClassMetadata =
-          static_cast<const ::ClassMetadata *>(getDirectType()))
-      return swift_getObjCClassMetadata(ClassMetadata);
+          static_cast<const ::ClassMetadata *>(getDirectType())) {
+      return getMetadataForClass(ClassMetadata);
+    }
     else
       return nullptr;
   default:
diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h
index 0740d8c..7ad8ec9 100644
--- a/stdlib/public/runtime/Private.h
+++ b/stdlib/public/runtime/Private.h
@@ -190,6 +190,14 @@
                      void (*function)(void *));
 #endif
 
+  static inline const Metadata *getMetadataForClass(const ClassMetadata *c) {
+#if SWIFT_OBJC_INTEROP
+    return swift_getObjCClassMetadata(c);
+#else
+    return c;
+#endif
+  }
+
 } // end namespace swift
 
 #endif /* SWIFT_RUNTIME_PRIVATE_H */
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index bd3ce06..2bb5ee1 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -108,14 +108,14 @@
     // metadata. The class additionally may be weak-linked, so we have to check
     // for null.
     if (auto *ClassMetadata = *getIndirectClass())
-      return swift_getObjCClassMetadata(ClassMetadata);
+      return getMetadataForClass(ClassMetadata);
     return nullptr;
       
   case TypeMetadataRecordKind::UniqueDirectClass:
     // The class may be ObjC, in which case we need to instantiate its Swift
     // metadata.
     if (auto *ClassMetadata = getDirectClass())
-      return swift_getObjCClassMetadata(ClassMetadata);
+      return getMetadataForClass(ClassMetadata);
     return nullptr;
       
   case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
@@ -136,7 +136,8 @@
     return getStaticWitnessTable();
 
   case ProtocolConformanceReferenceKind::WitnessTableAccessor:
-    return getWitnessTableAccessor()(type);
+    // FIXME: this needs information about conditional conformances.
+    return getWitnessTableAccessor()(type, nullptr, 0);
   }
 
   swift_runtime_unreachable(
@@ -394,7 +395,7 @@
   // If the type is a class, try its superclass.
   if (const ClassMetadata *classType = type->getClassObject()) {
     if (classHasSuperclass(classType)) {
-      type = swift_getObjCClassMetadata(classType->SuperClass);
+      type = getMetadataForClass(classType->SuperClass);
       goto recur;
     }
   }
@@ -433,7 +434,7 @@
     // If the type is a class, try its superclass.
     if (const ClassMetadata *classType = type->getClassObject()) {
       if (classHasSuperclass(classType)) {
-        type = swift_getObjCClassMetadata(classType->SuperClass);
+        type = getMetadataForClass(classType->SuperClass);
         continue;
       }
     }
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
index f407811..be6dc26 100644
--- a/stdlib/public/runtime/Reflection.mm
+++ b/stdlib/public/runtime/Reflection.mm
@@ -295,7 +295,7 @@
                                                     const Metadata *type) {
   void *object = *reinterpret_cast<void * const *>(value);
   auto isa = _swift_getClass(object);
-  return swift_getObjCClassMetadata(isa);
+  return getMetadataForClass(isa);
 }
 
 static std::tuple<const Metadata *, const OpaqueValue *>
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index d007461..80fa66a 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -105,12 +105,7 @@
 const Metadata *swift::swift_getObjectType(HeapObject *object) {
   auto classAsMetadata = _swift_getClass(object);
 
-#if !SWIFT_OBJC_INTEROP
-  assert(classAsMetadata &&
-         classAsMetadata->isTypeMetadata() &&
-         !classAsMetadata->isArtificialSubclass());
-  return classAsMetadata;
-#else
+#if SWIFT_OBJC_INTEROP
   // Walk up the superclass chain skipping over artifical Swift classes.
   // If we find a non-Swift class use the result of [object class] instead.
 
@@ -129,6 +124,11 @@
   }
   classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass);
   return swift_getObjCClassMetadata(classAsMetadata);
+#else
+  assert(classAsMetadata &&
+         classAsMetadata->isTypeMetadata() &&
+         !classAsMetadata->isArtificialSubclass());
+  return classAsMetadata;
 #endif
 }
 
diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 09c7661..0c1fedf 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 #endif
 #include <climits>
+#include <clocale>
 #include <cstdarg>
 #include <cstdint>
 #include <cstdio>
diff --git a/test/ClangImporter/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index 545cab8..51a6692 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -5,7 +5,7 @@
 // REQUIRES: objc_interop
 // REQUIRES: OS=macosx
 
-// CHECK: [[B:%TSo1BC]] = type
+// CHECK: %TSo1BC = type
 
 import ObjectiveC
 import Foundation
@@ -18,7 +18,7 @@
 // CHECK: @"\01L_selector_data(method:separateExtMethod:)" = private global [26 x i8] c"method:separateExtMethod:\00", section "__TEXT,__objc_methname,cstring_literals"
 
 // Instance method invocation
-// CHECK: define hidden swiftcc void @_T07objc_ir15instanceMethodsySo1BCF([[B]]*
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir15instanceMethodsySo1BCF(%TSo1BC*
 func instanceMethods(_ b: B) {
   // CHECK: load i8*, i8** @"\01L_selector(method:withFloat:)"
   // CHECK: call i32 bitcast (void ()* @objc_msgSend to i32
@@ -28,7 +28,7 @@
   i = i + b.method(1, with: 2.5 as Double)
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir16extensionMethodsySo1BC1b_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir16extensionMethodsySo1BC1b_tF
 func extensionMethods(b b: B) {
   // CHECK:      load i8*, i8** @"\01L_selector(method:separateExtMethod:)", align 8
   // CHECK:      [[T0:%.*]] = call i8* bitcast (void ()* @objc_msgSend to i8*
@@ -38,18 +38,18 @@
   b.method(1, separateExtMethod:1.5)
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir19initCallToAllocInitys5Int32V1i_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19initCallToAllocInitys5Int32V1i_tF
 func initCallToAllocInit(i i: CInt) {
   // CHECK: call {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
  
   B(int: i)
 }
 
-// CHECK: linkonce_odr hidden {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
+// CHECK-LABEL: linkonce_odr hidden {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
 // CHECK: call [[OPAQUE:%.*]]* @objc_allocWithZone
 
 // Indexed subscripting
-// CHECK: define hidden swiftcc void @_T07objc_ir19indexedSubscriptingySo1BC1b_Si3idxSo1AC1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19indexedSubscriptingySo1BC1b_Si3idxSo1AC1atF
 func indexedSubscripting(b b: B, idx: Int, a: A) {
   // CHECK: load i8*, i8** @"\01L_selector(setObject:atIndexedSubscript:)", align 8
   b[idx] = a
@@ -58,7 +58,7 @@
   var a2 = b[idx] as! A
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir17keyedSubscriptingySo1BC1b_So1AC3idxAG1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir17keyedSubscriptingySo1BC1b_So1AC3idxAG1atF
 func keyedSubscripting(b b: B, idx: A, a: A) {
   // CHECK: load i8*, i8** @"\01L_selector(setObject:forKeyedSubscript:)"
   b[a] = a
@@ -66,20 +66,19 @@
   var a2 = b[a] as! A
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir14propertyAccessySo1BC1b_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir14propertyAccessySo1BC1b_tF
 func propertyAccess(b b: B) {
    // CHECK: load i8*, i8** @"\01L_selector(counter)"
    // CHECK: load i8*, i8** @"\01L_selector(setCounter:)"
    b.counter = b.counter + 1
 
-   // CHECK: call %swift.type* @_T0So1BCMa()
-   // CHECK: bitcast %swift.type* {{%.+}} to %objc_class*
+   // CHECK: load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
    // CHECK: load i8*, i8** @"\01L_selector(sharedCounter)"
    // CHECK: load i8*, i8** @"\01L_selector(setSharedCounter:)"
    B.sharedCounter = B.sharedCounter + 1
 }
 
-// CHECK: define hidden swiftcc [[B]]* @_T07objc_ir8downcastSo1BCSo1AC1a_tF(
+// CHECK-LABEL: define hidden swiftcc %TSo1BC* @_T07objc_ir8downcastSo1BCSo1AC1a_tF(
 func downcast(a a: A) -> B {
   // CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
   // CHECK: [[T0:%.*]] = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* [[CLASS]])
@@ -88,12 +87,12 @@
   return a as! B
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir19almostSubscriptableySo06AlmostD0C3as1_So1AC1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19almostSubscriptableySo06AlmostD0C3as1_So1AC1atF
 func almostSubscriptable(as1 as1: AlmostSubscriptable, a: A) {
   as1.objectForKeyedSubscript(a)
 }
 
-// CHECK: define hidden swiftcc void @_T07objc_ir13protocolTypesySo7NSMinceC1a_So9NSRuncing_p1btF(%TSo7NSMinceC*, %objc_object*) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir13protocolTypesySo7NSMinceC1a_So9NSRuncing_p1btF(%TSo7NSMinceC*, %objc_object*) {{.*}} {
 func protocolTypes(a a: NSMince, b: NSRuncing) {
   // - (void)eatWith:(id <NSRuncing>)runcer;
   a.eat(with: b)
diff --git a/test/Compatibility/accessibility.swift b/test/Compatibility/accessibility.swift
new file mode 100644
index 0000000..fda6d32
--- /dev/null
+++ b/test/Compatibility/accessibility.swift
@@ -0,0 +1,689 @@
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+public protocol PublicProto {
+  func publicReq()
+}
+
+// expected-note@+1 * {{type declared here}}
+internal protocol InternalProto {
+  func internalReq()
+}
+
+fileprivate protocol FilePrivateProto {
+  func filePrivateReq()
+}
+
+// expected-note@+1 * {{type declared here}}
+private protocol PrivateProto {
+  func privateReq()
+}
+
+public struct PublicStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+  private func publicReq() {} // expected-error {{method 'publicReq()' must be declared public because it matches a requirement in public protocol 'PublicProto'}} {{3-10=public}}
+  private func internalReq() {} // expected-error {{method 'internalReq()' must be declared internal because it matches a requirement in internal protocol 'InternalProto'}} {{3-10=internal}}
+  private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+  private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+  public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+internal struct InternalStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+  private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=internal}}
+  private func internalReq() {} // expected-error {{method 'internalReq()' must be declared internal because it matches a requirement in internal protocol 'InternalProto'}} {{3-10=internal}}
+  private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+  private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+  public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+fileprivate struct FilePrivateStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+  private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=fileprivate}}
+  private func internalReq() {} // expected-error {{method 'internalReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'InternalProto'}} {{3-10=fileprivate}}
+  private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+  private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+  public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+private struct PrivateStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+  private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=fileprivate}}
+  private func internalReq() {} // expected-error {{method 'internalReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'InternalProto'}} {{3-10=fileprivate}}
+  private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+  private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+  public var publicVar = 0
+}
+
+extension PublicStruct {
+  public init(x: Int) { self.init() }
+}
+
+extension InternalStruct {
+  public init(x: Int) { self.init() }
+}
+
+extension FilePrivateStruct {
+  public init(x: Int) { self.init() }
+}
+
+extension PrivateStruct {
+  public init(x: Int) { self.init() }
+}
+
+public extension PublicStruct {
+  public func extMemberPublic() {}
+  private func extImplPublic() {}
+}
+internal extension PublicStruct {
+  public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+  private func extImplInternal() {}
+}
+private extension PublicStruct {
+  public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+  private func extImplPrivate() {}
+}
+fileprivate extension PublicStruct {
+  public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+  private func extImplFilePrivate() {}
+}
+public extension InternalStruct { // expected-error {{extension of internal struct cannot be declared public}} {{1-8=}}
+  public func extMemberPublic() {}
+  private func extImplPublic() {}
+}
+internal extension InternalStruct {
+  public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+  private func extImplInternal() {}
+}
+fileprivate extension InternalStruct {
+  public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+  private func extImplFilePrivate() {}
+}
+private extension InternalStruct {
+  public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+  private func extImplPrivate() {}
+}
+public extension FilePrivateStruct { // expected-error {{extension of fileprivate struct cannot be declared public}} {{1-8=}}
+  public func extMemberPublic() {}
+  private func extImplPublic() {}
+}
+internal extension FilePrivateStruct { // expected-error {{extension of fileprivate struct cannot be declared internal}} {{1-10=}}
+  public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+  private func extImplInternal() {}
+}
+fileprivate extension FilePrivateStruct {
+  public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+  private func extImplFilePrivate() {}
+}
+private extension FilePrivateStruct {
+  public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+  private func extImplPrivate() {}
+}
+public extension PrivateStruct { // expected-error {{extension of private struct cannot be declared public}} {{1-8=}}
+  public func extMemberPublic() {}
+  private func extImplPublic() {}
+}
+internal extension PrivateStruct { // expected-error {{extension of private struct cannot be declared internal}} {{1-10=}}
+  public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+  private func extImplInternal() {}
+}
+fileprivate extension PrivateStruct { // expected-error {{extension of private struct cannot be declared fileprivate}} {{1-13=}}
+  public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+  private func extImplFilePrivate() {}
+}
+private extension PrivateStruct {
+  public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+  private func extImplPrivate() {}
+}
+
+
+public struct PublicStructDefaultMethods: PublicProto, InternalProto, PrivateProto {
+  func publicReq() {} // expected-error {{method 'publicReq()' must be declared public because it matches a requirement in public protocol 'PublicProto'}} {{3-3=public }}
+  func internalReq() {}
+  func privateReq() {}
+}
+
+
+public class Base {
+  required public init() {}
+  // expected-note@+1 * {{overridden declaration is here}}
+  public func foo() {}
+  // expected-note@+1 * {{overridden declaration is here}}
+  public internal(set) var bar: Int = 0
+  // expected-note@+1 * {{overridden declaration is here}}
+  public subscript () -> () { return () }
+}
+
+
+public extension Base {
+  open func extMemberPublic() {} // expected-warning {{declaring open instance method in public extension}}
+}
+internal extension Base {
+  open func extMemberInternal() {} // expected-warning {{declaring open instance method in an internal extension}}
+}
+
+public class PublicSub: Base {
+  required init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-12=public }}
+  override func foo() {} // expected-error {{overriding instance method must be as accessible as the declaration it overrides}} {{12-12=public }}
+  override var bar: Int { // expected-error {{overriding var must be as accessible as the declaration it overrides}} {{12-12=public }}
+    get { return 0 }
+    set {}
+  }
+  override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as the declaration it overrides}} {{12-12=public }}
+}
+
+internal class InternalSub: Base {
+  required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=internal}}
+  private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=internal}}
+  private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=internal}}
+    get { return 0 }
+    set {}
+  }
+  private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=internal}}
+}
+
+internal class InternalSubGood: Base {
+  required init() {} // no-warning
+  override func foo() {}
+  override var bar: Int {
+    get { return 0 }
+    set {}
+  }
+  override subscript () -> () { return () }
+}
+
+internal class InternalSubPrivateSet: Base {
+  required init() {}
+  private(set) override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-16=}}
+    get { return 0 }
+    set {}
+  }
+  private(set) override subscript () -> () { // okay; read-only in base class
+    get { return () }
+    set {}
+  }
+}
+
+fileprivate class FilePrivateSub: Base {
+  required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=fileprivate}}
+  private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+  private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+    get { return 0 }
+    set {}
+  }
+  private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+}
+
+fileprivate class FilePrivateSubGood: Base {
+  required init() {} // no-warning
+  override func foo() {}
+  override var bar: Int {
+    get { return 0 }
+    set {}
+  }
+  override subscript () -> () { return () }
+}
+
+fileprivate class FilePrivateSubGood2: Base {
+  fileprivate required init() {} // no-warning
+  fileprivate override func foo() {}
+  fileprivate override var bar: Int {
+    get { return 0 }
+    set {}
+  }
+  fileprivate override subscript () -> () { return () }
+}
+
+fileprivate class FilePrivateSubPrivateSet: Base {
+  required init() {}
+  private(set) override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+    get { return 0 }
+    set {}
+  }
+  private(set) override subscript () -> () { // okay; read-only in base class
+    get { return () }
+    set {}
+  }
+}
+
+private class PrivateSub: Base {
+  required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=fileprivate}}
+  private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+  private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+    get { return 0 }
+    set {}
+  }
+  private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+}
+
+private class PrivateSubGood: Base {
+  required fileprivate init() {}
+  fileprivate override func foo() {}
+  fileprivate override var bar: Int {
+    get { return 0 }
+    set {}
+  }
+  fileprivate override subscript () -> () { return () }
+}
+
+private class PrivateSubPrivateSet: Base {
+  required fileprivate init() {}
+  fileprivate override func foo() {}
+  private(set) override var bar: Int { // expected-error {{setter of overriding var must be as accessible as its enclosing type}}
+    get { return 0 }
+    set {}
+  }
+  private(set) override subscript () -> () { // okay; read-only in base class
+    get { return () }
+    set {}
+  }
+}
+
+public typealias PublicTA1 = PublicStruct
+public typealias PublicTA2 = InternalStruct // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias PublicTA3 = FilePrivateStruct // expected-error {{type alias cannot be declared public because its underlying type uses a fileprivate type}}
+public typealias PublicTA4 = PrivateStruct // expected-error {{type alias cannot be declared public because its underlying type uses a private type}}
+
+// expected-note@+1 {{type declared here}}
+internal typealias InternalTA1 = PublicStruct
+internal typealias InternalTA2 = InternalStruct
+internal typealias InternalTA3 = FilePrivateStruct // expected-error {{type alias cannot be declared internal because its underlying type uses a fileprivate type}}
+internal typealias InternalTA4 = PrivateStruct // expected-error {{type alias cannot be declared internal because its underlying type uses a private type}}
+
+public typealias PublicFromInternal = InternalTA1 // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+
+typealias FunctionType1 = (PrivateStruct) -> PublicStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias FunctionType2 = (PublicStruct) -> PrivateStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias FunctionType3 = (PrivateStruct) -> PrivateStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+
+typealias ArrayType = [PrivateStruct] // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias DictType = [String : PrivateStruct] // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias GenericArgs = Optional<PrivateStruct> // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+
+
+public protocol HasAssocType {
+  associatedtype Inferred
+  func test(input: Inferred)
+}
+
+public struct AssocTypeImpl: HasAssocType {
+  public func test(input: Bool) {}
+}
+public let _: AssocTypeImpl.Inferred?
+
+
+public let x: PrivateStruct = PrivateStruct() // expected-error {{constant cannot be declared public because its type uses a private type}}
+public var a: PrivateStruct?, b: PrivateStruct? // expected-error 2 {{variable cannot be declared public because its type uses a private type}}
+public var (c, d): (PrivateStruct?, PrivateStruct?) // expected-error {{variable cannot be declared public because its type uses a private type}}
+
+var internalVar: PrivateStruct? // expected-error {{variable must be declared private or fileprivate because its type uses a private type}}
+
+let internalConstant = PrivateStruct() // expected-error {{constant must be declared private or fileprivate because its type 'PrivateStruct' uses a private type}}
+public let publicConstant = [InternalStruct]() // expected-error {{constant cannot be declared public because its type '[InternalStruct]' uses an internal type}}
+
+public struct Properties {
+  public let x: PrivateStruct = PrivateStruct() // expected-error {{property cannot be declared public because its type uses a private type}}
+  public var a: PrivateStruct?, b: PrivateStruct? // expected-error 2 {{property cannot be declared public because its type uses a private type}}
+  public var (c, d): (PrivateStruct?, PrivateStruct?) // expected-error {{property cannot be declared public because its type uses a private type}}
+
+  let y = PrivateStruct() // expected-error {{property must be declared fileprivate because its type 'PrivateStruct' uses a private type}}
+}
+
+public struct Subscripts {
+  subscript (a: PrivateStruct) -> Int { return 0 } // expected-error {{subscript must be declared fileprivate because its index uses a private type}}
+  subscript (a: Int) -> PrivateStruct { return PrivateStruct() } // expected-error {{subscript must be declared fileprivate because its element type uses a private type}}
+
+  public subscript (a: PrivateStruct, b: Int) -> Int { return 0 } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+  public subscript (a: Int, b: PrivateStruct) -> Int { return 0 } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+  public subscript (a: InternalStruct, b: PrivateStruct) -> InternalStruct { return InternalStruct() } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+  public subscript (a: PrivateStruct, b: InternalStruct) -> PrivateStruct { return PrivateStruct() } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+  public subscript (a: Int, b: Int) -> InternalStruct { return InternalStruct() } // expected-error {{subscript cannot be declared public because its element type uses an internal type}}
+}
+
+public struct Methods {
+  func foo(a: PrivateStruct) -> Int { return 0 } // expected-error {{method must be declared fileprivate because its parameter uses a private type}}
+  func bar(a: Int) -> PrivateStruct { return PrivateStruct() } // expected-error {{method must be declared fileprivate because its result uses a private type}}
+
+  public func a(a: PrivateStruct, b: Int) -> Int { return 0 } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+  public func b(a: Int, b: PrivateStruct) -> Int { return 0 } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+  public func c(a: InternalStruct, b: PrivateStruct) -> InternalStruct { return InternalStruct() } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+  public func d(a: PrivateStruct, b: InternalStruct) -> PrivateStruct { return PrivateStruct() } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+  public func e(a: Int, b: Int) -> InternalStruct { return InternalStruct() } // expected-error {{method cannot be declared public because its result uses an internal type}}
+}
+
+func privateParam(a: PrivateStruct) {} // expected-error {{function must be declared private or fileprivate because its parameter uses a private type}}
+
+public struct Initializers {
+  init(a: PrivateStruct) {} // expected-error {{initializer must be declared fileprivate because its parameter uses a private type}}
+
+  public init(a: PrivateStruct, b: Int) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+  public init(a: Int, b: PrivateStruct) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+  public init(a: InternalStruct, b: PrivateStruct) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+  public init(a: PrivateStruct, b: InternalStruct) { } // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+}
+
+
+public class PublicClass {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalClass {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateClass {}
+
+public protocol AssocTypes {
+  associatedtype Foo
+
+  associatedtype Internal: InternalClass // expected-error {{associated type in a public protocol uses an internal type in its requirement}}
+  associatedtype InternalConformer: InternalProto // expected-error {{associated type in a public protocol uses an internal type in its requirement}}
+
+  associatedtype PrivateConformer: PrivateProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+  associatedtype PI: PrivateProto, InternalProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+  associatedtype IP: InternalProto, PrivateProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+
+  associatedtype PrivateDefault = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its default definition}}
+  associatedtype PublicDefault = PublicStruct
+  associatedtype PrivateDefaultConformer: PublicProto = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its default definition}}
+  associatedtype PublicDefaultConformer: PrivateProto = PublicStruct // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+  associatedtype PrivatePrivateDefaultConformer: PrivateProto = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+  associatedtype PublicPublicDefaultConformer: PublicProto = PublicStruct
+}
+
+public protocol RequirementTypes {
+  var x: PrivateStruct { get } // expected-error {{property cannot be declared public because its type uses a private type}}
+  subscript(x: Int) -> InternalStruct { get set } // expected-error {{subscript cannot be declared public because its element type uses an internal type}}
+  func foo() -> PrivateStruct // expected-error {{method cannot be declared public because its result uses a private type}}
+  init(x: PrivateStruct) // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+}
+
+protocol DefaultRefinesPrivate : PrivateProto {} // expected-error {{protocol must be declared private or fileprivate because it refines a private protocol}}
+public protocol PublicRefinesPrivate : PrivateProto {} // expected-error {{public protocol cannot refine a private protocol}}
+public protocol PublicRefinesInternal : InternalProto {} // expected-error {{public protocol cannot refine an internal protocol}}
+public protocol PublicRefinesPI : PrivateProto, InternalProto {} // expected-error {{public protocol cannot refine a private protocol}}
+public protocol PublicRefinesIP : InternalProto, PrivateProto {} // expected-error {{public protocol cannot refine a private protocol}}
+
+
+// expected-note@+1 * {{type declared here}}
+private typealias PrivateInt = Int
+enum DefaultRawPrivate : PrivateInt { // expected-error {{enum must be declared private or fileprivate because its raw type uses a private type}}
+  case A
+}
+public enum PublicRawPrivate : PrivateInt { // expected-error {{enum cannot be declared public because its raw type uses a private type}}
+  case A
+}
+public enum MultipleConformance : PrivateProto, PrivateInt { // expected-error {{enum cannot be declared public because its raw type uses a private type}} expected-error {{must appear first}} {{35-35=PrivateInt, }} {{47-59=}}
+  case A
+  func privateReq() {}
+}
+
+open class OpenSubclassInternal : InternalClass {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalClass' of open class must be open}}
+public class PublicSubclassPublic : PublicClass {}
+public class PublicSubclassInternal : InternalClass {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicSubclassPrivate : PrivateClass {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+class DefaultSubclassPublic : PublicClass {}
+class DefaultSubclassInternal : InternalClass {}
+class DefaultSubclassPrivate : PrivateClass {} // expected-error {{class must be declared private or fileprivate because its superclass is private}}
+
+public class PublicGenericClass<T> {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalGenericClass<T> {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateGenericClass<T> {}
+
+open class OpenConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-warning {{class should not be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<Int>' of open class must be open}}
+public class PublicConcreteSubclassPublic : PublicGenericClass<Int> {}
+public class PublicConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-warning {{class should not be declared public because its superclass is internal}}
+public class PublicConcreteSubclassPrivate : PrivateGenericClass<Int> {} // expected-warning {{class should not be declared public because its superclass is private}}
+public class PublicConcreteSubclassPublicPrivateArg : PublicGenericClass<PrivateStruct> {} // expected-warning {{class should not be declared public because its superclass is private}}
+
+open class OpenGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-warning {{class should not be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<T>' of open class must be open}}
+public class PublicGenericSubclassPublic<T> : PublicGenericClass<T> {}
+public class PublicGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-warning {{class should not be declared public because its superclass is internal}}
+public class PublicGenericSubclassPrivate<T> : PrivateGenericClass<T> {} // expected-warning {{class should not be declared public because its superclass is private}}
+
+
+
+public enum PublicEnumPrivate {
+  case A(PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
+}
+enum DefaultEnumPrivate {
+  case A(PrivateStruct) // expected-error {{enum case in an internal enum uses a private type}}
+}
+public enum PublicEnumPI {
+  case A(InternalStruct) // expected-error {{enum case in a public enum uses an internal type}}
+  case B(PrivateStruct, InternalStruct) // expected-error {{enum case in a public enum uses a private type}}
+  case C(InternalStruct, PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
+}
+enum DefaultEnumPublic {
+  case A(PublicStruct) // no-warning
+}
+
+
+struct DefaultGeneric<T> {}
+
+struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
+struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
+struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error  {{same-type requirement makes generic parameter 'T' non-generic}}
+// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
+struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
+
+public struct PublicGenericInternal<T: InternalProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses an internal type}}
+
+public struct PublicGenericPI<T: PrivateProto, U: InternalProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericIP<T: InternalProto, U: PrivateProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericPIReq<T: PrivateProto> where T: InternalProto {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericIPReq<T: InternalProto> where T: PrivateProto {} // expected-error {{generic struct cannot be declared public because its generic requirement uses a private type}}
+
+public func genericFunc<T: InternalProto>(_: T) {} // expected-error {{function cannot be declared public because its generic parameter uses an internal type}} {}
+public class GenericClass<T: InternalProto> { // expected-error {{generic class cannot be declared public because its generic parameter uses an internal type}}
+  public init<T: PrivateProto>(_: T) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}}
+  public func genericMethod<T: PrivateProto>(_: T) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}}
+}
+public enum GenericEnum<T: InternalProto> { // expected-error {{generic enum cannot be declared public because its generic parameter uses an internal type}}
+  case A
+}
+
+
+public protocol PublicMutationOperations {
+  var size: Int { get set }
+  subscript (_: Int) -> Int { get set }
+}
+
+internal protocol InternalMutationOperations {
+  var size: Int { get set }
+  subscript (_: Int) -> Int { get set }
+}
+
+public struct AccessorsControl : InternalMutationOperations {
+  private var size = 0 // expected-error {{property 'size' must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{3-10=internal}}
+  private subscript (_: Int) -> Int { // expected-error {{subscript must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{3-10=internal}}
+    get { return 42 }
+    set {}
+  }
+}
+
+public struct PrivateSettersPublic : InternalMutationOperations {
+  // Please don't change the formatting here; it's a precise fix-it test.
+  public private(set) var size = 0 // expected-error {{setter for property 'size' must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{10-17=internal}}
+  public private(set) subscript (_: Int) -> Int { // expected-error {{subscript setter must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{10-17=internal}}
+    get { return 42 }
+    set {}
+  }
+}
+
+internal struct PrivateSettersInternal : PublicMutationOperations {
+  // Please don't change the formatting here; it's a precise fix-it test.
+  private(set)var size = 0 // expected-error {{setter for property 'size' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicMutationOperations'}} {{3-15=}}
+
+  internal private(set)subscript (_: Int) -> Int { // expected-error {{subscript setter must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicMutationOperations'}} {{12-24=}}
+    get { return 42 }
+    set {}
+  }
+}
+
+public protocol PublicReadOnlyOperations {
+  var size: Int { get }
+  subscript (_: Int) -> Int { get }
+}
+
+internal struct PrivateSettersForReadOnlyInternal : PublicReadOnlyOperations {
+  public private(set) var size = 0
+  internal private(set) subscript (_: Int) -> Int { // no-warning
+    get { return 42 }
+    set {}
+  }
+}
+
+public struct PrivateSettersForReadOnlyPublic : PublicReadOnlyOperations {
+  public private(set) var size = 0 // no-warning
+  internal private(set) subscript (_: Int) -> Int { // expected-error {{subscript must be declared public because it matches a requirement in public protocol 'PublicReadOnlyOperations'}} {{3-11=public}}
+    get { return 42 }
+    set {}
+  }
+}
+
+
+public protocol PublicOperatorProto {
+  static prefix func !(_: Self) -> Self
+}
+
+internal protocol InternalOperatorProto {
+  static prefix func !(_: Self) -> Self
+}
+
+fileprivate protocol FilePrivateOperatorProto {
+  static prefix func !(_: Self) -> Self
+}
+
+private protocol PrivateOperatorProto {
+  static prefix func !(_: Self) -> Self
+}
+
+public struct PublicOperatorAdopter : PublicOperatorProto {
+  fileprivate struct Inner : PublicOperatorProto {
+  }
+}
+private prefix func !(input: PublicOperatorAdopter) -> PublicOperatorAdopter { // expected-error {{method '!' must be declared public because it matches a requirement in public protocol 'PublicOperatorProto'}} {{1-8=public}}
+  return input
+}
+private prefix func !(input: PublicOperatorAdopter.Inner) -> PublicOperatorAdopter.Inner {
+  return input
+}
+
+public struct InternalOperatorAdopter : InternalOperatorProto {
+  fileprivate struct Inner : InternalOperatorProto {
+  }
+}
+private prefix func !(input: InternalOperatorAdopter) -> InternalOperatorAdopter { // expected-error {{method '!' must be declared internal because it matches a requirement in internal protocol 'InternalOperatorProto'}} {{1-8=internal}}
+  return input
+}
+private prefix func !(input: InternalOperatorAdopter.Inner) -> InternalOperatorAdopter.Inner {
+  return input
+}
+
+public struct FilePrivateOperatorAdopter : FilePrivateOperatorProto {
+  fileprivate struct Inner : FilePrivateOperatorProto {
+  }
+}
+private prefix func !(input: FilePrivateOperatorAdopter) -> FilePrivateOperatorAdopter {
+  return input
+}
+private prefix func !(input: FilePrivateOperatorAdopter.Inner) -> FilePrivateOperatorAdopter.Inner {
+  return input
+}
+
+public struct PrivateOperatorAdopter : PrivateOperatorProto {
+  fileprivate struct Inner : PrivateOperatorProto {
+  }
+}
+private prefix func !(input: PrivateOperatorAdopter) -> PrivateOperatorAdopter {
+  return input
+}
+private prefix func !(input: PrivateOperatorAdopter.Inner) -> PrivateOperatorAdopter.Inner {
+  return input
+}
+
+
+public protocol Equatablish {
+  static func ==(lhs: Self, rhs: Self) /* -> bool */ // expected-note {{protocol requires function '=='}}
+}
+
+fileprivate struct EquatablishOuter {
+  internal struct Inner : Equatablish {}
+}
+private func ==(lhs: EquatablishOuter.Inner, rhs: EquatablishOuter.Inner) {}
+// expected-note@-1 {{candidate has non-matching type}}
+
+fileprivate struct EquatablishOuter2 {
+  internal struct Inner : Equatablish {
+    fileprivate static func ==(lhs: Inner, rhs: Inner) {}
+    // expected-note@-1 {{candidate has non-matching type}}
+  }
+}
+
+fileprivate struct EquatablishOuterProblem {
+  internal struct Inner : Equatablish { // expected-error {{type 'EquatablishOuterProblem.Inner' does not conform to protocol 'Equatablish'}}
+    private static func ==(lhs: Inner, rhs: Inner) {}
+  }
+}
+
+internal struct EquatablishOuterProblem2 {
+  public struct Inner : Equatablish {
+    fileprivate static func ==(lhs: Inner, rhs: Inner) {} // expected-error {{method '==' must be as accessible as its enclosing type because it matches a requirement in protocol 'Equatablish'}} {{5-16=internal}}
+    // expected-note@-1 {{candidate has non-matching type}}
+  }
+}
+
+internal struct EquatablishOuterProblem3 {
+  public struct Inner : Equatablish {
+  }
+}
+private func ==(lhs: EquatablishOuterProblem3.Inner, rhs: EquatablishOuterProblem3.Inner) {} // expected-error {{method '==' must be as accessible as its enclosing type because it matches a requirement in protocol 'Equatablish'}} {{1-8=internal}}
+// expected-note@-1 {{candidate has non-matching type}}
+
+
+public protocol AssocTypeProto {
+  associatedtype Assoc
+}
+
+fileprivate struct AssocTypeOuter {
+  internal struct Inner : AssocTypeProto {
+    fileprivate typealias Assoc = Int
+  }
+}
+
+fileprivate struct AssocTypeOuterProblem {
+  internal struct Inner : AssocTypeProto {
+    private typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-12=fileprivate}}
+  }
+}
+
+internal struct AssocTypeOuterProblem2 {
+  public struct Inner : AssocTypeProto {
+    fileprivate typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-16=internal}}
+  }
+}
+
+internal typealias InternalComposition = PublicClass & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalComposition : InternalComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+internal typealias InternalGenericComposition<T> = PublicGenericClass<T> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalGenericComposition : InternalGenericComposition<Int> { // expected-warning {{class should not be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+internal typealias InternalConcreteGenericComposition = PublicGenericClass<Int> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalConcreteGenericComposition : InternalConcreteGenericComposition { // expected-warning {{class should not be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+public typealias BadPublicComposition1 = InternalClass & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition2 = PublicClass & InternalProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition3<T> = InternalGenericClass<T> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition4 = InternalGenericClass<Int> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition5 = PublicGenericClass<InternalStruct> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift
index 5b52394..1ba1e45 100644
--- a/test/Constraints/bridging.swift
+++ b/test/Constraints/bridging.swift
@@ -181,8 +181,9 @@
 struct NotEquatable {}
 func notEquatableError(_ d: Dictionary<Int, NotEquatable>) -> Bool {
   // FIXME: Another awful diagnostic.
-  return d == d // expected-error{{binary operator '==' cannot be applied to two 'Dictionary<Int, NotEquatable>' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+  return d == d // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+  // expected-note @-2 {{requirement from conditional conformance of 'Dictionary<Int, NotEquatable>' to 'Equatable'}}
 }
 
 // NSString -> String
diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift
index c128c4b..efac19a 100644
--- a/test/Constraints/dictionary_literal.swift
+++ b/test/Constraints/dictionary_literal.swift
@@ -72,10 +72,10 @@
   // expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any>'; add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any>}}
 
   let _: [String : Any] = ["a" : 1, "b" : 2.5, "c" : "hello"]
-  
+
   let _ = ["a" : 1, "b" : nil, "c" : "hello"]
   // expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any?>'; add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any?>}}
-  
+
   let _: [String : Any?] = ["a" : 1, "b" : nil, "c" : "hello"]
 
   let d2 = [:]
@@ -102,8 +102,7 @@
 func rdar32330004_1() -> [String: Any] {
   return ["a""one": 1, "two": 2, "three": 3] // expected-note {{did you mean to use a dictionary literal instead?}}
   // expected-error@-1 2 {{expected ',' separator}}
-  // expected-error@-2 {{expected expression in container literal}}
-  // expected-error@-3 {{contextual type '[String : Any]' cannot be used with array literal}}
+  // expected-error@-2 {{contextual type '[String : Any]' cannot be used with array literal}}
 }
 
 func rdar32330004_2() -> [String: Any] {
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index b56e228..022c4e1 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -163,9 +163,8 @@
 default: break
 }
 
-// <rdar://problem/21995744> QoI: Binary operator '~=' cannot be applied to operands of type 'String' and 'String?'
 switch ("foo" as String?) {
-case "what": break // expected-error{{expression pattern of type 'String' cannot match values of type 'String?'}} {{12-12=?}}
+case "what": break
 default: break
 }
 
diff --git a/test/DebugInfo/basic.swift b/test/DebugInfo/basic.swift
index 4f9673a..bbc2bc6 100644
--- a/test/DebugInfo/basic.swift
+++ b/test/DebugInfo/basic.swift
@@ -1,5 +1,3 @@
-// FIXME(integers): started to fail due to the new integer protocols
-// XFAIL: *
 // A (no longer) basic test for debug info.
 // --------------------------------------------------------------------
 // Verify that we don't emit any debug info by default.
@@ -43,8 +41,8 @@
      // CHECK-DAG: store i64 %1, i64* [[BADDR:.*]], align
      // CHECK-DAG: [[AVAL:%.*]] = getelementptr inbounds {{.*}}, [[AMEM:.*]], i32 0, i32 0
      // CHECK-DAG: [[BVAL:%.*]] = getelementptr inbounds {{.*}}, [[BMEM:.*]], i32 0, i32 0
-     // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[AADDR]], metadata ![[AARG:.*]], metadata !{{[0-9]+}}), !dbg ![[ASCOPE]]
-     // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[BADDR]], metadata ![[BARG:.*]], metadata !{{[0-9]+}})
+     // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[AADDR]], metadata ![[AARG:.*]], metadata !DIExpression()), !dbg ![[ASCOPE]]
+     // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[BADDR]], metadata ![[BARG:.*]], metadata !DIExpression())
      // CHECK-DAG: ![[AARG]] = !DILocalVariable(name: "a", arg: 1
      // CHECK-DAG: ![[BARG]] = !DILocalVariable(name: "b", arg: 2
      if b != 0 {
@@ -53,7 +51,7 @@
        // CHECK-DAG: smul{{.*}}, !dbg ![[MUL:[0-9]+]]
        // CHECK-DAG: [[MUL]] = !DILocation(line: [[@LINE+4]], column: 16,
        // Runtime call to multiply function:
-       // CHECK-NOSIL: @_T0s1mois5Int64VAC_ACtF{{.*}}, !dbg ![[MUL:[0-9]+]]
+       // CHECK-NOSIL: @_T0s5Int64V1moiA2B_ABtFZ{{.*}}, !dbg ![[MUL:[0-9]+]]
        // CHECK-NOSIL: [[MUL]] = !DILocation(line: [[@LINE+1]], column: 16,
        return a*b
      } else {
@@ -79,7 +77,7 @@
 // CHECK-DAG: ![[INT64:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int64", {{.*}}, identifier: "_T0s5Int64VD")
 // CHECK-DAG: ![[PARAMTYPES]] = !{![[INT64]], ![[INT64]], ![[INT64]]}
 // Import of the main module with the implicit name.
-// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[MAINFILE]], entity: ![[MAINMODULE:[0-9]+]], file: ![[MAINFILE]], line: 1)
+// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[MAINFILE]], entity: ![[MAINMODULE:[0-9]+]], file: ![[MAINFILE]])
 // CHECK-DAG: ![[MAINMODULE]] = !DIModule({{.*}}, name: "basic"
 
 // DWARF Version
diff --git a/test/DebugInfo/callexpr.swift b/test/DebugInfo/callexpr.swift
index 4b738f2..e401c12 100644
--- a/test/DebugInfo/callexpr.swift
+++ b/test/DebugInfo/callexpr.swift
@@ -9,8 +9,9 @@
 // CHECK: call {{.*}}foo{{.*}}, !dbg ![[ARG1:.*]]
 // CHECK: call {{.*}}foo{{.*}}, !dbg ![[ARG2:.*]]
 // CHECK: call {{.*}}foo{{.*}}, !dbg ![[OUTER:.*]]
-let r = foo(foo(1, 23), // CHECK: ![[ARG1]] = !DILocation(line: [[@LINE]],
+let r = foo(
+            foo(1, 23), // CHECK: ![[ARG1]] = !DILocation(line: [[@LINE]],
             foo(2, 42)  // CHECK: ![[ARG2]] = !DILocation(line: [[@LINE]],
-           )            // CHECK: ![[OUTER]] = !DILocation(line: [[@LINE]],
+           )            // CHECK: ![[OUTER]] = !DILocation(line: [[@LINE-3]],
 markUsed(r)
 
diff --git a/test/DebugInfo/inlinedAt.swift b/test/DebugInfo/inlinedAt.swift
index 2d781ea..40e47ef 100644
--- a/test/DebugInfo/inlinedAt.swift
+++ b/test/DebugInfo/inlinedAt.swift
@@ -40,7 +40,7 @@
 // CHECK: ![[F:.*]] = distinct !DISubprogram(name: "f",
 // CHECK: ![[G:.*]] = distinct !DISubprogram(name: "g",
 
-// CHECK: ![[L3:.*]] = !DILocation(line: 302, column: 13,
+// CHECK: ![[L3:.*]] = !DILocation(line: 302, column: 10,
 // CHECK-SAME:                     scope: ![[F_SCOPE:.*]])
 // CHECK: ![[F_SCOPE]] = distinct !DILexicalBlock(scope: ![[F]],
 // CHECK-SAME:                                    line: 301, column: 33)
@@ -49,6 +49,6 @@
 // CHECK: ![[H:.*]] = distinct !DISubprogram(name: "h",
 // CHECK: ![[L1]] = !DILocation(line: 101, column: 8, scope: ![[H]],
 // CHECK-SAME:                  inlinedAt: ![[L2:.*]])
-// CHECK: ![[L2]] = !DILocation(line: 203, column: 13, scope: ![[G_SCOPE]],
+// CHECK: ![[L2]] = !DILocation(line: 203, column: 10, scope: ![[G_SCOPE]],
 // CHECK-SAME:                  inlinedAt: ![[L3]])
 
diff --git a/test/DebugInfo/linetable-assign.swift b/test/DebugInfo/linetable-assign.swift
new file mode 100644
index 0000000..f679808
--- /dev/null
+++ b/test/DebugInfo/linetable-assign.swift
@@ -0,0 +1,17 @@
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle %s \
+// RUN:   -emit-sil -emit-verbose-sil -Xllvm -sil-print-debuginfo -g -o - \
+// RUN:   | %FileCheck %s
+public func g<T>(_ t: T) {}
+public func f(_ i: Int32) {
+  // CHECK: function_ref @_T04main1fys5Int32VFyycfU_
+  // CHECK-SAME: loc "{{.*}}":13:3,
+  // CHECK: %[[CLOSURE:.*]] = partial_apply
+  // CHECK-SAME: loc "{{.*}}":13:3,{{.*}}auto_gen
+  // CHECK: store %[[CLOSURE]]
+  // CHECK-SAME: loc "{{.*}}":12:3,  
+  var closure = // line 12
+  {
+    g(i)
+  }
+  return closure() 
+}
diff --git a/test/DebugInfo/linetable-cleanups.swift b/test/DebugInfo/linetable-cleanups.swift
index 9183355..4531191 100644
--- a/test/DebugInfo/linetable-cleanups.swift
+++ b/test/DebugInfo/linetable-cleanups.swift
@@ -27,7 +27,8 @@
 // CHECK:  call void @swift_bridgeObjectRelease({{.*}}) {{#[0-9]+}}, !dbg ![[CLEANUPS:.*]]
 // CHECK-NEXT:  !dbg ![[CLEANUPS]]
 // CHECK-NEXT:  llvm.lifetime.end
-// CHECK-NEXT:  bitcast
+// CHECK-NEXT:  load
+// CHECK-NEXT:  swift_rt_swift_release
 // CHECK-NEXT:  bitcast
 // CHECK-NEXT:  llvm.lifetime.end
 // CHECK-NEXT:  ret void, !dbg ![[CLEANUPS]]
diff --git a/test/DebugInfo/linetable.swift b/test/DebugInfo/linetable.swift
index 3a020f8..489b15e 100644
--- a/test/DebugInfo/linetable.swift
+++ b/test/DebugInfo/linetable.swift
@@ -22,14 +22,14 @@
 }
 
 func main(_ x: Int64) -> Void
-// CHECK: define hidden {{.*}} void @_T09linetable4main{{[_0-9a-zA-Z]*}}F
+// CHECK-LABEL: define hidden {{.*}} void @_T09linetable4main{{[_0-9a-zA-Z]*}}F
 {
     var my_class = MyClass(input: 10)
 // Linetable continuity. Don't go into the closure expression.
 // ASM-CHECK: .loc [[FILEID:[0-9]]] [[@LINE+1]] 5
     call_me (
 // ASM-CHECK-NOT: .loc [[FILEID]] [[@LINE+1]] 5
-// CHECK: define {{.*}} @_T09linetable4mainys5Int64VFyycfU_Tf2in_n({{.*}})
+// CHECK-LABEL: define {{.*}} @_T09linetable4mainys5Int64VFyycfU_Tf2in_n({{.*}})
         {
             var result = my_class.do_something(x)
             markUsed(result)
diff --git a/test/DebugInfo/patternmatching.swift b/test/DebugInfo/patternmatching.swift
index d9c8f33..b98d31a 100644
--- a/test/DebugInfo/patternmatching.swift
+++ b/test/DebugInfo/patternmatching.swift
@@ -15,10 +15,9 @@
 switch p {
     case (let x, let y) where
       // CHECK:   call {{.*}}double {{.*}}return_same{{.*}}, !dbg ![[LOC1:.*]]
-      // CHECK: br {{.*}}, label {{.*}}, label {{.*}}, !dbg ![[LOC2:.*]]
+      // CHECK: br {{.*}}, label {{.*}}, label {{.*}}, !dbg ![[LOC1]]
       // CHECK: call{{.*}}markUsed{{.*}}, !dbg ![[LOC3:.*]]
-      // CHECK: ![[LOC1]] = !DILocation(line: [[@LINE+2]],
-      // CHECK: ![[LOC2]] = !DILocation(line: [[@LINE+1]],
+      // CHECK: ![[LOC1]] = !DILocation(line: [[@LINE+1]],
                         return_same(x) == return_same(y):
       // CHECK: ![[LOC3]] = !DILocation(line: [[@LINE+1]],
       markUsed(x)
diff --git a/test/DebugInfo/return.swift b/test/DebugInfo/return.swift
index bf7057d..5bff35e 100644
--- a/test/DebugInfo/return.swift
+++ b/test/DebugInfo/return.swift
@@ -7,16 +7,19 @@
 
 // CHECK: define {{.*}}ifelseexpr
 public func ifelseexpr() -> Int64 {
-  var x = X(i:0) 
+  var x = X(i:0)
+  // CHECK: [[ALLOCA:%.*]] = alloca %T6return1XC*
   // CHECK: [[META:%.*]] = call %swift.type* @_T06return1XCMa()
   // CHECK: [[X:%.*]] = call {{.*}}%T6return1XC* @_T06return1XCACs5Int64V1i_tcfC(
   // CHECK-SAME:                                  i64 0, %swift.type* swiftself [[META]])
+  // CHECK:  store %T6return1XC* [[X]], %T6return1XC** [[ALLOCA]]
   // CHECK:  @swift_rt_swift_release to void (%T6return1XC*)*)(%T6return1XC* [[X]])
   if true {
     x.x += 1
   } else {
     x.x -= 1
   }
+  // CHECK:  [[X:%.*]] = load %T6return1XC*, %T6return1XC** [[ALLOCA]]
   // CHECK:  @swift_rt_swift_release to void (%T6return1XC*)*)(%T6return1XC* [[X]])
   // CHECK-SAME:                    , !dbg ![[RELEASE:.*]]
 
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index f31301d..1cbdc47 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -4,6 +4,7 @@
 _TtBO ---> Builtin.UnknownObject
 _TtBo ---> Builtin.NativeObject
 _TtBp ---> Builtin.RawPointer
+_TtBt ---> Builtin.SILToken
 _TtBv4Bi8_ ---> Builtin.Vec4xInt8
 _TtBv4Bf16_ ---> Builtin.Vec4xFloat16
 _TtBv4Bp ---> Builtin.Vec4xRawPointer
diff --git a/test/Driver/actions.swift b/test/Driver/actions.swift
index cc8ee4d..3e21f12 100644
--- a/test/Driver/actions.swift
+++ b/test/Driver/actions.swift
@@ -28,6 +28,19 @@
 // BASICMODULE: 1: compile, {0}, swiftmodule
 // BASICMODULE: 2: merge-module, {1}, swiftmodule
 
+// RUN: touch %t/a.swiftmodule
+// RUN: %swiftc_driver -driver-print-actions -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
+// RUN: %swiftc_driver -driver-print-actions -g -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-DEBUG-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-DEBUG-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-DEBUG-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-DEBUG-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
 // RUN: %swiftc_driver -driver-print-actions -emit-executable -emit-module %s 2>&1 | %FileCheck %s -check-prefix=EXEC-AND-MODULE
 // EXEC-AND-MODULE: 0: input, "{{.*}}actions.swift", swift
 // EXEC-AND-MODULE: 1: compile, {0}, object
@@ -114,9 +127,8 @@
 // DEBUG-LINK-ONLY: 1: input, "{{.*}}/b.o", object
 // DEBUG-LINK-ONLY: 2: input, "{{.*}}/a.swiftmodule", swiftmodule
 // DEBUG-LINK-ONLY: 3: input, "{{.*}}/b.swiftmodule", swiftmodule
-// DEBUG-LINK-ONLY: 4: merge-module, {2, 3}, swiftmodule
-// DEBUG-LINK-ONLY: 5: link, {0, 1, 4}, image
-// DEBUG-LINK-ONLY: 6: generate-dSYM, {5}, dSYM
+// DEBUG-LINK-ONLY: 4: link, {0, 1, 2, 3}, image
+// DEBUG-LINK-ONLY: 5: generate-dSYM, {4}, dSYM
 
 // RUN: touch %t/c.swift
 // RUN: %swiftc_driver -driver-print-actions %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-SWIFTMODULES
@@ -128,6 +140,16 @@
 // LINK-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
 // LINK-SWIFTMODULES: 6: link, {1, 2, 3, 4, 5}, image
 
+// RUN: %swiftc_driver -driver-print-actions -g %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-DEBUG-SWIFTMODULES
+// LINK-DEBUG-SWIFTMODULES: 0: input, "{{.*}}/c.swift", swift
+// LINK-DEBUG-SWIFTMODULES: 1: compile, {0}, object
+// LINK-DEBUG-SWIFTMODULES: 2: input, "{{.*}}/a.o", object
+// LINK-DEBUG-SWIFTMODULES: 3: input, "{{.*}}/b.o", object
+// LINK-DEBUG-SWIFTMODULES: 4: input, "{{.*}}/a.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 6: merge-module, {1}, swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 7: link, {1, 2, 3, 4, 5, 6}, image
+
 // RUN: touch %t/a.o %t/b.o
 // RUN: %swiftc_driver -driver-print-actions %t/a.o %s -o main 2>&1 | %FileCheck %s -check-prefix=COMPILE-PLUS-OBJECT
 // COMPILE-PLUS-OBJECT: 0: input, "{{.*}}/a.o", object
diff --git a/test/Driver/bindings.swift b/test/Driver/bindings.swift
index 423c61b..c516545 100644
--- a/test/Driver/bindings.swift
+++ b/test/Driver/bindings.swift
@@ -50,5 +50,5 @@
 
 // RUN: touch %t/a.swiftmodule %t/b.swiftmodule
 // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -g %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=DEBUG-LINK-ONLY
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {swiftmodule: "[[MERGED:.+\.swiftmodule]]", swiftdoc: "{{.+}}.swiftdoc"}
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "[[MERGED]]"], output: {image: "main"}
+// DEBUG-LINK-ONLY-NOT: "swift"
+// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {image: "main"}
diff --git a/test/Driver/filelists.swift b/test/Driver/filelists.swift
index a5e605d..6d9132e 100644
--- a/test/Driver/filelists.swift
+++ b/test/Driver/filelists.swift
@@ -42,8 +42,8 @@
 // RUN: ls %t/tmp-crash/sources-* %t/tmp-crash/outputs-*
 
 
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
 
 // CHECK-LINK: Handled link
 
diff --git a/test/Driver/opt-record.swift b/test/Driver/opt-record.swift
index 823f519..15fcd93 100644
--- a/test/Driver/opt-record.swift
+++ b/test/Driver/opt-record.swift
@@ -20,15 +20,15 @@
   // YAML-NEXT:   File:            {{.*}}opt-record.swift
   // YAML-NEXT:   Line:            42
   // YAML-NEXT:   Column:          3
-  // YAML-NEXT: Function:        _T012optrecordmod3baryyF
+  // YAML-NEXT: Function:        'bar()'
   // YAML-NEXT: Args:
-  // YAML-NEXT:   - Callee:          _T012optrecordmod3fooyyF
+  // YAML-NEXT:   - Callee:          '"foo()"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}opt-record.swift
   // YAML-NEXT:       Line:            11
   // YAML-NEXT:       Column:          6
   // YAML-NEXT:   - String:          ' inlined into '
-  // YAML-NEXT:   - Caller:          _T012optrecordmod3baryyF
+  // YAML-NEXT:   - Caller:          '"bar()"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}opt-record.swift
   // YAML-NEXT:       Line:            15
diff --git a/test/Driver/opt-remark.swift b/test/Driver/opt-remark.swift
index 0e54d56..aa2fb52 100644
--- a/test/Driver/opt-remark.swift
+++ b/test/Driver/opt-remark.swift
@@ -38,11 +38,11 @@
 
 func foo() {
   // REMARK_MISSED-NOT: remark: {{.*}} inlined
-  // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+  // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline function "big()" (cost = {{.*}}, benefit = {{.*}})
   // REMARK_MISSED-NOT: remark: {{.*}} inlined
 	big()
   // REMARK_PASSED-NOT: remark: Not profitable
-  // REMARK_PASSED: opt-remark.swift:47:3: remark: _T04null5smallyyF inlined into _T04null3fooyyF (cost = {{.*}}, benefit = {{.*}})
+  // REMARK_PASSED: opt-remark.swift:47:3: remark: "small()" inlined into "foo()" (cost = {{.*}}, benefit = {{.*}})
   // REMARK_PASSED-NOT: remark: Not profitable
   small()
 }
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 3d8889b..6e32e9c 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -6,11 +6,16 @@
 protocol P2 {}
 protocol P3 {}
 protocol P4: P1 {}
+protocol P5: P2 {}
+// expected-note@-1{{type 'InheritImplicitGood<T>' does not conform to inherited protocol 'P2'}}
+// expected-note@-2{{type 'InheritImplicitBad<T>' does not conform to inherited protocol 'P2'}}
+protocol P6: P2 {}
+// expected-note@-1{{type 'InheritImplicitBad<T>' does not conform to inherited protocol 'P2'}}
 
 protocol Assoc { associatedtype AT }
 
 func takes_P2<X: P2>(_: X) {}
-// expected-note@-1{{in call to function 'takes_P2'}}
+
 // expected-note@-2{{candidate requires that the types 'U' and 'V' be equivalent (requirement specified as 'U' == 'V')}}
 // expected-note@-3{{requirement from conditional conformance of 'SameTypeGeneric<U, V>' to 'P2'}}
 // expected-note@-4{{candidate requires that the types 'U' and 'Int' be equivalent (requirement specified as 'U' == 'Int')}}
@@ -21,6 +26,9 @@
 // expected-note@-9{{requirement from conditional conformance of 'ClassFree<U>' to 'P2'}}
 // expected-note@-10{{candidate requires that 'C3' inherit from 'U' (requirement specified as 'U' : 'C3')}}
 // expected-note@-11{{requirement from conditional conformance of 'ClassMoreSpecific<U>' to 'P2'}}
+// expected-note@-12{{candidate requires that 'C1' inherit from 'Int' (requirement specified as 'Int' : 'C1')}}
+// expected-note@-13{{requirement from conditional conformance of 'SubclassBad' to 'P2'}}
+func takes_P5<X: P5>(_: X) {}
 
 struct Free<T> {}
 // CHECK-LABEL: ExtensionDecl line={{.*}} base=Free<T>
@@ -83,13 +91,8 @@
 // CHECK-NEXT: (normal_conformance type=SameType<Int> protocol=P2
 // CHECK-NEXT:   same_type: τ_0_0 Int)
 extension SameType: P2 where T == Int {}
-// FIXME: the compiler gets this... exactly backwards. :( For the incorrectly
-// accepted cases, it seems the compiler ends up with a (specialized_conformance
-// type=SameType<Float> ... same_type: Int Int ...) for the (normal_conformance
-// type=SameType<Int> ...).
 func same_type_good() {
     takes_P2(SameType<Int>())
-    // expected-error@-1{{generic parameter 'X' could not be inferred}}
 }
 func same_type_bad<U>(_: U) {
     takes_P2(SameType<U>())
@@ -190,6 +193,116 @@
 extension ClassLessSpecific: P2 where T: C1 {}
 
 
+// Inherited conformances:
+class Base<T> {}
+extension Base: P2 where T: C1 {}
+
+class SubclassGood: Base<C1> {}
+func subclass_good() {
+  takes_P2(SubclassGood())
+}
+class SubclassBad: Base<Int> {}
+func subclass_bad() {
+  takes_P2(SubclassBad())
+  // expected-error@-1{{cannot invoke 'takes_P2(_:)' with an argument list of type '(SubclassBad)'}}
+}
+
+// Inheriting conformances:
+
+struct InheritEqual<T> {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
+// CHECK-NEXT:  (normal_conformance type=InheritEqual<T> protocol=P2
+// CHECK-NEXT:    conforms_to: τ_0_0 P1)
+extension InheritEqual: P2 where T: P1 {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
+// CHECK-NEXT:  (normal_conformance type=InheritEqual<T> protocol=P5
+// CHECK-NEXT:    conforms_to: τ_0_0 P1)
+extension InheritEqual: P5 where T: P1 {}
+func inheritequal_good<U: P1>(_: U) {
+  takes_P2(InheritEqual<U>())
+  takes_P5(InheritEqual<U>())
+}
+func inheritequal_bad<U>(_: U) {
+  takes_P2(InheritEqual<U>())
+  // expected-error@-1{{'<X where X : P2> (X) -> ()' requires that 'U' conform to 'P1'}}
+  // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+  // expected-note@-3{{requirement from conditional conformance of 'InheritEqual<U>' to 'P2'}}
+  takes_P5(InheritEqual<U>())
+  // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P1'}}
+  // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+  // expected-note@-3{{requirement from conditional conformance of 'InheritEqual<U>' to 'P5'}}
+}
+
+struct InheritLess<T> {}
+extension InheritLess: P2 where T: P1 {}
+extension InheritLess: P5 {}
+// expected-error@-1{{'P5' requires that 'T' conform to 'P1'}}
+// expected-note@-2{{requirement specified as 'T' : 'P1'}}
+// expected-note@-3{{requirement from conditional conformance of 'InheritLess<T>' to 'P2'}}
+
+
+struct InheritMore<T> {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
+// CHECK-NEXT:  (normal_conformance type=InheritMore<T> protocol=P2
+// CHECK-NEXT:    conforms_to: τ_0_0 P1)
+extension InheritMore: P2 where T: P1 {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
+// CHECK-NEXT:  (normal_conformance type=InheritMore<T> protocol=P5
+// CHECK-NEXT:    conforms_to: τ_0_0 P4)
+extension InheritMore: P5 where T: P4 {}
+func inheritequal_good_good<U: P4>(_: U) {
+  takes_P2(InheritMore<U>())
+  takes_P5(InheritMore<U>())
+}
+func inheritequal_good_bad<U: P1>(_: U) {
+  takes_P2(InheritMore<U>())
+  takes_P5(InheritMore<U>())
+  // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P4'}}
+  // expected-note@-2{{requirement specified as 'U' : 'P4'}}
+  // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P5'}}
+}
+func inheritequal_bad_bad<U>(_: U) {
+  takes_P2(InheritMore<U>())
+  // expected-error@-1{{'<X where X : P2> (X) -> ()' requires that 'U' conform to 'P1'}}
+  // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+  // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P2'}}
+  takes_P5(InheritMore<U>())
+  // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P4'}}
+  // expected-note@-2{{requirement specified as 'U' : 'P4'}}
+  // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P5'}}
+}
+
+struct InheritImplicitGood<T> {}
+// FIXME: per SE-0143, this should result in an implicit conformance
+// InheritImplicitGood: P2.
+extension InheritImplicitGood: P5 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitGood<T>' does not conform to protocol 'P2'}}
+
+struct InheritImplicitBad<T> {}
+// This shouldn't give anything implicit since either conformance could imply
+// InheritImplicitBad: P2.
+extension InheritImplicitBad: P5 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitBad<T>' does not conform to protocol 'P2'}}
+extension InheritImplicitBad: P6 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitBad<T>' does not conform to protocol 'P2'}}
+
+
+
+// "Multiple conformances" from SE0143
+
+struct TwoConformances<T> {}
+extension TwoConformances: P2 where T: P1 {}
+// expected-error@-1{{redundant conformance of 'TwoConformances<T>' to protocol 'P2'}}
+extension TwoConformances: P2 where T: P3 {}
+// expected-note@-1{{'TwoConformances<T>' declares conformance to protocol 'P2' here}}
+
+struct TwoDisjointConformances<T> {}
+extension TwoDisjointConformances: P2 where T == Int {}
+// expected-error@-1{{redundant conformance of 'TwoDisjointConformances<T>' to protocol 'P2'}}
+extension TwoDisjointConformances: P2 where T == String {}
+// expected-note@-1{{'TwoDisjointConformances<T>' declares conformance to protocol 'P2' here}}
+
+
 // FIXME: these cases should be equivalent (and both with the same output as the
 // first), but the second one choses T as the representative of the
 // equivalence class containing both T and U in the extension's generic
diff --git a/test/Generics/conditional_conformances_execute_smoke.swift b/test/Generics/conditional_conformances_execute_smoke.swift
new file mode 100644
index 0000000..eb2ad6f
--- /dev/null
+++ b/test/Generics/conditional_conformances_execute_smoke.swift
@@ -0,0 +1,84 @@
+// RUN: %target-run-simple-swift | %FileCheck %s
+
+// Smoke test to see that various conditional conformances correctly execute
+
+protocol P1 {
+  func method1()
+}
+var isp1_count = 0
+struct IsP1: P1 {
+  var id: Int
+  init() {
+    id = isp1_count
+    isp1_count += 1
+  }
+  func method1() {
+    print("IsP1", id)
+  }
+}
+protocol P2 {
+  func method2()
+}
+protocol P3 {
+  func method3()
+}
+protocol P4: P1 {
+  func method4()
+}
+
+protocol Assoc { associatedtype AT }
+
+func takes_P2<X: P2>(_ x: X) {
+  x.method2()
+}
+
+struct NoRecur<T> {
+  var x: T
+}
+extension NoRecur: P2 where T: P1 {
+  func method2() {
+    print("NoRecur")
+    x.method1()
+  }
+}
+
+var noRecur = NoRecur(x: IsP1())
+print("noRecur.method2()")
+noRecur.method2()
+// CHECK-LABEL: noRecur.method2()
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 0
+
+print("takes_P2(NoRecur(...))")
+takes_P2(NoRecur(x: IsP1()))
+// CHECK-LABEL: takes_P2(NoRecur(...))
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 1
+
+struct Recur<T> {
+  var id: Int
+  var x: T
+}
+extension Recur: P2 where T: P2 {
+  func method2() {
+    print("Recur", id)
+    x.method2()
+  }
+}
+
+var recur = Recur(id: 0, x: Recur(id: 1, x: NoRecur(x: IsP1())))
+print("recur.method2()")
+recur.method2()
+// CHECK-LABEL: recur.method2()
+// CHECK-NEXT: Recur 0
+// CHECK-NEXT: Recur 1
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 2
+
+print("takes_P2(Recur(...))")
+takes_P2(Recur(id: 2, x: Recur(id: 3, x: NoRecur(x: IsP1()))))
+// CHECK-LABEL: takes_P2(Recur(...))
+// CHECK-NEXT: Recur 2
+// CHECK-NEXT: Recur 3
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 3
diff --git a/test/Generics/conditional_conformances_operators.swift b/test/Generics/conditional_conformances_operators.swift
new file mode 100644
index 0000000..91b6a54
--- /dev/null
+++ b/test/Generics/conditional_conformances_operators.swift
@@ -0,0 +1,17 @@
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify
+
+// rdar://problem/35480952
+
+postfix operator %%%
+protocol P {
+  static postfix func %%%(lhs: Self)
+}
+protocol Q {}
+struct Foo<T> {}
+extension Foo: P where T : Q {
+  static postfix func %%%(lhs: Foo<T>) {}
+}
+
+func useIt<T: Q>(_: T.Type) {
+  Foo<T>()%%%
+}
diff --git a/test/Generics/validate_stdlib_generic_signatures.swift b/test/Generics/validate_stdlib_generic_signatures.swift
new file mode 100644
index 0000000..eae4985
--- /dev/null
+++ b/test/Generics/validate_stdlib_generic_signatures.swift
@@ -0,0 +1,6 @@
+// Verifies that all of the generic signatures in the standard library are
+// minimal and canonical.
+
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify-generic-signatures Swift
+
+// expected-no-diagnostics
diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift
index 934643e..5bffd1b 100644
--- a/test/IRGen/abitypes.swift
+++ b/test/IRGen/abitypes.swift
@@ -214,9 +214,8 @@
 
   // x86_64-macosx:      define hidden i8* @_T08abitypes3FooC9copyClass{{[_0-9a-zA-Z]*}}FTo(i8*, i8*, i8*) unnamed_addr {{.*}} {
   // x86_64-macosx:      [[VALUE:%[0-9]+]] = call swiftcc [[TYPE:%.*]]* @_T08abitypes3FooC9copyClass{{[_0-9a-zA-Z]*}}F
-  // x86_64-macosx:      [[T0:%.*]] = phi [[TYPE]]* [ [[VALUE]],
-  // x86_64-macosx:      [[T1:%.*]] = bitcast [[TYPE]]* [[T0]] to [[OBJC:%objc_class]]*
-  // x86_64-macosx:      [[RESULT:%[0-9]+]] = bitcast [[OBJC]]* [[T1]] to i8*
+  // x86_64-macosx:      [[T0:%.*]] = call [[OBJC:%objc_class]]* @swift_getObjCClassFromMetadata([[TYPE]]* [[VALUE]])
+  // x86_64-macosx:      [[RESULT:%[0-9]+]] = bitcast [[OBJC]]* [[T0]] to i8*
   // x86_64-macosx:      ret i8* [[RESULT]]
   dynamic func copyClass(_ a: AnyClass) -> AnyClass {
     return a
diff --git a/test/IRGen/associated_type_witness.swift b/test/IRGen/associated_type_witness.swift
index 933102a..83a6746 100644
--- a/test/IRGen/associated_type_witness.swift
+++ b/test/IRGen/associated_type_witness.swift
@@ -117,10 +117,16 @@
 // CHECK-NEXT:    store atomic %swift.type* [[FETCH_RESULT]], %swift.type** [[CACHE]] release, align 8
 // CHECK-NEXT:    br label %cont
 
-//   Witness table instantiation function for Computed : Assocked.
-// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWa(%swift.type*)
+//   Witness table accessor function for Computed : Assocked.
+// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWa(%swift.type*, i8***, i64)
 // CHECK:         entry:
-// CHECK-NEXT:     [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG, %swift.type* %0, i8** null)
+// CHECK-NEXT:     %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT:     [[TABLES:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT:     store i8*** %1, i8**** [[TABLES]], align 8
+// CHECK-NEXT:     [[COUNT:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:     store i64 %2, i64* [[COUNT]], align 8
+// CHECK-NEXT:     [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:     [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG, %swift.type* %0, i8** [[INSTANTIATION_ARGS]])
 // CHECK-NEXT:     ret i8** [[WTABLE]]
 
 
@@ -151,17 +157,23 @@
 
 //   Instantiation function for GenericComputed : DerivedFromSimpleAssoc.
 // CHECK-LABEL: define internal void @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI(i8**, %swift.type*, i8**)
-// CHECK:         [[T0:%.*]] = call i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type* %1)
+// CHECK:         [[T0:%.*]] = call i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type* %1, i8*** undef, i64 0)
 // CHECK-NEXT:    [[T1:%.*]] = bitcast i8** [[T0]] to i8*
 // CHECK-NEXT:    [[T2:%.*]] = getelementptr inbounds i8*, i8** %0, i32 0
 // CHECK-NEXT:    store i8* [[T1]], i8** [[T2]], align 8
 // CHECK-NEXT:    ret void
 
-//   Witness table instantiation function for GenericComputed : HasSimpleAssoc..
-// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type*)
+//   Witness table accessor function for GenericComputed : HasSimpleAssoc..
+// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type*, i8***, i64)
 // CHECK-NEXT:   entry:
-// CHECK-NEXT:    [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWG, %swift.type* %0, i8** null)
-// CHECK-NEXT:    ret i8** %1
+// CHECK-NEXT:    %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT:    [[TABLES:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT:    store i8*** %1, i8**** [[TABLES]], align 8
+// CHECK-NEXT:    [[COUNT:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:    store i64 %2, i64* [[COUNT]], align 8
+// CHECK-NEXT:    [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:    [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWG, %swift.type* %0, i8** [[INSTANTIATION_ARGS]])
+// CHECK-NEXT:    ret i8** [[WTABLE]]
 
 
 protocol HasAssocked {
diff --git a/test/IRGen/c_function_pointer.sil b/test/IRGen/c_function_pointer.sil
index 760918c..8f74c62 100644
--- a/test/IRGen/c_function_pointer.sil
+++ b/test/IRGen/c_function_pointer.sil
@@ -27,5 +27,4 @@
 
 // CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T0yyXCMa()
 // --                                                                               0x3000001 -- C convention, 1 argument
-// CHECK:         call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 196608, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index 573a13b..21ea905 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -91,10 +91,10 @@
   // CHECK: [[WITNESS_FUNC:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %swift.type*, i8**)
   // CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* swiftself %0, %swift.type* {{.*}}, i8** [[INHERITED_WTBL]])
   x.classBoundBinaryMethod(y)
+  // CHECK: call %objc_object* @swift_unknownRetain(%objc_object* returned [[Y:%.*]])
   // CHECK: [[WITNESS_ENTRY:%.*]] = getelementptr inbounds i8*, i8** %T.ClassBoundBinary, i32 1
   // CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ENTRY]], align 8
   // CHECK: [[WITNESS_FUNC:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %objc_object*, %swift.type*, i8**)
-  // CHECK: call %objc_object* @swift_unknownRetain(%objc_object* returned [[Y:%.*]])
   // CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* [[Y]], %objc_object* swiftself %0, %swift.type* %T, i8** %T.ClassBoundBinary)
 }
 
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e7c2b20..5a4851d 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -13,14 +13,14 @@
 // CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvpWvd = {{(protected )?}}global [[INT]] 0
 // CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvpWvd = {{(protected )?}}global [[INT]] 0
 
-// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{12|16}}
+// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{8|16}}
 // CHECK: @_T016class_resilience21ResilientGenericChildC5fields5Int32VvpWvi = {{(protected )?}}global [[INT]] {{56|88}}
 
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|20}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|20}}
 
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|24}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|24}}
 
 import resilient_class
 import resilient_struct
diff --git a/test/IRGen/conditional_conformances.swift b/test/IRGen/conditional_conformances.swift
new file mode 100644
index 0000000..c8b6a2c
--- /dev/null
+++ b/test/IRGen/conditional_conformances.swift
@@ -0,0 +1,7 @@
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift
+
+// Too many pointer-sized integers in the IR
+// REQUIRES: PTRSIZE=64
+
diff --git a/test/IRGen/dynamic_cast_functions.swift b/test/IRGen/dynamic_cast_functions.swift
index a6dc73e..16f6141 100644
--- a/test/IRGen/dynamic_cast_functions.swift
+++ b/test/IRGen/dynamic_cast_functions.swift
@@ -48,3 +48,72 @@
 
 // CHECK: ok
 print((t1 == t2) ? "fail" : "ok")
+
+let i: (inout Int) -> Void = { _ in }
+let j: (__shared Int) -> Void = { _ in }
+let k: (Int, inout Int) -> Void = { _,_ in }
+let l: (inout Int, Float, inout String) -> Void = { _,_,_ in }
+let m: (__shared Int, String, inout Float, Double) -> Void = { _,_,_,_ in }
+
+let i_any: Any = i
+let j_any: Any = j
+let k_any: Any = k
+let l_any: Any = l
+let m_any: Any = m
+
+// CHECK: ok
+print((i_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (__shared Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (inout Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((j_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (inout Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (__shared Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((k_any as? (Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (Int, inout Int) -> Void) != nil ? "ok" : "fail")
+// CHECK: ok
+print((k_any as? (inout Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (inout Int, __shared Int) -> Void) != nil ? "fail" : "ok")
+
+// CHECK: ok
+print((l_any as? (Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, Float, inout String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, __shared String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, inout String) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((m_any as? (Int, String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, __shared Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (inout Int, String, __shared Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, inout Float, Double) -> Void) != nil ? "ok" : "fail")
diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil
index 02c153a..2a57c9f 100644
--- a/test/IRGen/existentials_opaque_boxed.sil
+++ b/test/IRGen/existentials_opaque_boxed.sil
@@ -80,7 +80,7 @@
 // CHECK:  [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
 // CHECK:  [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
 // CHECK:  [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
-// CHECK:  [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64|i32)}} 48, {{(i64|i32)}} 7)
+// CHECK:  [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64 48|i32 40)}}, {{(i64|i32)}} 7)
 // CHECK:  [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>*
 // CHECK:  [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>, <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
 // CHECK:  [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14NotInlineFixedV*
@@ -136,7 +136,7 @@
 // CHECK:   [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
 // CHECK:   [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
 // CHECK:   [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK:   [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK:   [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
 // CHECK:   [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
 // CHECK:   [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
 // CHECK:   [[HEAPSIZE:%.*]] = add {{(i64|i32)}} [[ALIGNEDSTART]], [[SIZE]]
@@ -179,7 +179,7 @@
 // CHECK:   [[REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.refcounted**
 // CHECK:   [[REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFADDR]]
 // CHECK:   [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK:   [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK:   [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
 // CHECK:   [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
 // CHECK:   [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
 // CHECK:   [[HEAPOBJ:%.*]] = bitcast %swift.refcounted* %9 to i8*
@@ -519,8 +519,8 @@
 // CHECK:  [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
 // CHECK:  [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
 // CHECK:  [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), {{(i64|i32)}} 64, {{(i64|i32)}} 31)
-// CHECK:  [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>*
-// CHECK:  [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
+// CHECK:  [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>*
+// CHECK:  [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
 // CHECK:  [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14FixedOveralignV*
 // CHECK:  [[INLINEBUFFER_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %swift.refcounted**
 // CHECK:  store %swift.refcounted* [[BOX]], %swift.refcounted** [[INLINEBUFFER_ADDR]]
diff --git a/test/IRGen/function_metadata.swift b/test/IRGen/function_metadata.swift
index 5dec8d0..8cb6f87 100644
--- a/test/IRGen/function_metadata.swift
+++ b/test/IRGen/function_metadata.swift
@@ -4,45 +4,42 @@
 
 // CHECK: define hidden swiftcc void @_T017function_metadata9test_archyyF()
 func test_arch() {
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3) {{#[0-9]+}}
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 0, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch( {() -> () in } )
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
   arch({(x: Int) -> () in  })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* bitcast (%swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(_: ()) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1WithFlags([[WORD]] 33554433, %swift.type* @_T0SiN, i32 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(x: inout Int) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* %3, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* %2, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(x: (Int, Float)) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2WithFlags([[WORD]] 33554434, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SiN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(x: inout Int, y: Int) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(a: Float, b: Int) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SSN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3WithFlags([[WORD]] 33554435, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SfN, i32 0, %swift.type* @_T0SSN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(x: inout Int, y: Float, z: String) -> () in })
 
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, %swift.type* @_T0SfN, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(a: Float, b: Float, c: Int) -> () in })
 
-  // CHECK: [[T0:%.*]] = getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 0
-  // CHECK: store [[WORD]] 4
-  // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 1
-  // CHECK: store i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*)
-  // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 2
-  // CHECK: store i8* bitcast (%swift.type* @_T0SdN to i8*)
-  // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 3
-  // CHECK: store i8* bitcast (%swift.type* @_T0SSN to i8*)
-  // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 4
-  // CHECK: store i8* bitcast (%swift.type* @_T0s4Int8VN to i8*)
-  // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 5
-  // CHECK: store %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)
-  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** [[T0]]) {{#[0-9]+}}
+  // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+  // CHECK: store %swift.type* @_T0SiN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+  // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 1
+  // CHECK: store %swift.type* @_T0SdN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+  // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 2
+  // CHECK: store %swift.type* @_T0SSN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+  // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 3
+  // CHECK: store %swift.type* @_T0s4Int8VN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+  // CHECK: [[T:%.*]] = getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+  // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD]] 33554436, %swift.type** %7, i32* getelementptr inbounds ([4 x i32], [4 x i32]* @parameter-flags, i32 0, i32 0), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
   arch({(x: inout Int, y: Double, z: String, w: Int8) -> () in })
 }
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index 8e5d64e..56f038f 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -75,7 +75,7 @@
 // CHECK-SAME: <i32 0x8000_0004>,
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
 // CHECK-64-SAME: <i32 0x4000_0010> }>
 
 // -- %e: C.y
@@ -87,7 +87,7 @@
 // CHECK-SAME: <i32 0x8000_0004>,
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // -- 0x4000_0000 (class) + offset of C.y
-// CHECK-32-SAME: <i32 0x4000_0010> }>
+// CHECK-32-SAME: <i32 0x4000_000c> }>
 // CHECK-64-SAME: <i32 0x4000_0018> }>
 
 // -- %f: C.z
@@ -99,7 +99,7 @@
 // CHECK-SAME: <i32 0x8000_0004>,
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c> }>
+// CHECK-32-SAME: <i32 0x4000_0018> }>
 // CHECK-64-SAME: <i32 0x4000_0030> }>
 
 // -- %g: S.z.x
@@ -118,7 +118,7 @@
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // CHECK: %swift.type* (i8*)*
 // -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
 // CHECK-64-SAME: <i32 0x4000_0010> }>
 
 // -- %h: C.z.x
@@ -132,7 +132,7 @@
 // CHECK-64-SAME: <i32 0x8000_0014>,
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c>,
+// CHECK-32-SAME: <i32 0x4000_0018>,
 // CHECK-64-SAME: <i32 0x4000_0030>,
 // CHECK-64-SAME: [4 x i8] zeroinitializer,
 // CHECK: %swift.type* (i8*)*
diff --git a/test/IRGen/literals.sil b/test/IRGen/literals.sil
index ce5987b..b45a16b 100644
--- a/test/IRGen/literals.sil
+++ b/test/IRGen/literals.sil
@@ -7,11 +7,11 @@
 // CHECK: [[U16_0:@.*]] = private unnamed_addr constant [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0]
 // CHECK: [[U16_1:@.*]] = private unnamed_addr constant [4 x i16] [i16 0, i16 120, i16 427, i16 0]
 // CHECK: @_T0s19_UTF16StringStorageCN = external global %objc_class
-// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
-// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
+// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
+// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
 // CHECK: @_T0s20_Latin1StringStorageCN = external global %objc_class
-// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
-// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
+// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
+// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
 
 sil_stage canonical
 
diff --git a/test/IRGen/metatype.sil b/test/IRGen/metatype.sil
index 6d82c1d..ba052b9 100644
--- a/test/IRGen/metatype.sil
+++ b/test/IRGen/metatype.sil
@@ -31,10 +31,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc %objc_class* @foreign_thick_to_objc(%swift.type*)
 sil @foreign_thick_to_objc : $@convention(thin) (@thick Gizmo.Type) -> @objc_metatype Gizmo.Type {
 bb0(%0 : $@thick Gizmo.Type):
-  // CHECK: [[KIND_GEP:%[0-9A-Za-z_.]+]] = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0
-  // CHECK-NEXT: [[KIND:%[0-9A-Za-z_.]+]] = load i64, i64* [[KIND_GEP]], align 8
-  // CHECK-NEXT: [[IS_WRAPPER:%[0-9A-Za-z_.]+]] = icmp eq i64 [[KIND]], 14
-  // CHECK-NEXT: br i1
+  // CHECK: call %objc_class* @swift_getObjCClassFromMetadata
   %1 = thick_to_objc_metatype %0 : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
   // CHECK: ret %objc_class*
   return %1 : $@objc_metatype Gizmo.Type
@@ -61,12 +58,7 @@
 protocol CP: class {}
 
 // CHECK-LABEL: define{{( protected)?}} swiftcc %objc_class* @archetype_objc_metatype(%swift.type* %T, i8** %T.CP)
-// CHECK:         [[IS_OBJC_WRAPPER:%.*]] = icmp eq i64 {{%.*}}, 14
-// CHECK:         br i1 [[IS_OBJC_WRAPPER]], label %isWrapper, label %metadataForClass.cont
-// CHECK:       isWrapper:
-// CHECK:         [[WRAPPED_CLASS:%.*]] = load %swift.type*, %swift.type**
-// CHECK:       metadataForClass.cont:
-// CHECK:         phi %swift.type* [ %T, %entry ], [ [[WRAPPED_CLASS]], %isWrapper ]
+// CHECK:         call %objc_class* @swift_getObjCClassFromMetadata
 sil @archetype_objc_metatype : $@convention(thin) <T: CP> () -> @objc_metatype T.Type {
 entry:
   %m = metatype $@objc_metatype T.Type
diff --git a/test/IRGen/objc_block.sil b/test/IRGen/objc_block.sil
index ce8a344..3f6bf1b 100644
--- a/test/IRGen/objc_block.sil
+++ b/test/IRGen/objc_block.sil
@@ -38,5 +38,4 @@
 
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @generic_with_block(%objc_block** noalias nocapture dereferenceable({{.*}}))
 // --                                                                               0x100_0001 = block convention, 1 arg
-// CHECK:         call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 65536, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/IRGen/objc_class_empty_fields.swift b/test/IRGen/objc_class_empty_fields.swift
index 5a3e204..dfdb5fd 100644
--- a/test/IRGen/objc_class_empty_fields.swift
+++ b/test/IRGen/objc_class_empty_fields.swift
@@ -5,7 +5,7 @@
 // SR-1055
 
 // CHECK-64: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 16, i32 24
-// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 12, i32 16
+// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 8, i32 12
 
 enum OneCaseEnum {
     case X
diff --git a/test/IRGen/partial_apply_forwarder.sil b/test/IRGen/partial_apply_forwarder.sil
index 984c1e9..408a54f 100644
--- a/test/IRGen/partial_apply_forwarder.sil
+++ b/test/IRGen/partial_apply_forwarder.sil
@@ -94,7 +94,7 @@
 // CHECK:   [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
 // CHECK:   [[PARAMTYADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}}
 // CHECK:   %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[PARAMTYADDR]]
-// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
 // CHECK:   [[OBJ:%.*]] = bitcast %swift.refcounted* %0 to %T23partial_apply_forwarder7WeakBoxC.1*
 // CHECK:   tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[OBJ]], i8** [[WITNESS]])
 // CHECK: }
@@ -151,7 +151,7 @@
 // CHECK:   [[TYPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
 // CHECK:   [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 10|i32 13)}}
 // CHECK:   %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[TYPARAM]]
-// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
 // CHECK:   tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[CAST]], i8** [[WITNESS]])
 // CHECK:   ret void
 
@@ -203,7 +203,7 @@
 // CHECK:   [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
 // CHECK:   [[GENPARAMADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}}
 // CHECK:   %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[GENPARAMADDR]]
-// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK:   [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
 // CHECK:   tail call swiftcc void @takingQAndS(i64 [[X]], %T23partial_apply_forwarder7WeakBoxC.1* %.asUnsubstituted, i8** [[WITNESS]])
 
 sil public @bind_polymorphic_param_from_context_with_layout : $@convention(thin) <τ_0_1>(@in τ_0_1, S) -> @owned @callee_owned () -> () {
diff --git a/test/IRGen/partial_apply_objc.sil b/test/IRGen/partial_apply_objc.sil
index ffd59ee..d6c16ca 100644
--- a/test/IRGen/partial_apply_objc.sil
+++ b/test/IRGen/partial_apply_objc.sil
@@ -225,3 +225,49 @@
   %p = partial_apply %m(%c) : $@convention(objc_method) (Fob,  Gizmo) -> ()
   return %p : $@callee_owned (Fob) -> ()
 }
+
+// CHECK-LABEL: define {{.*}}@objc_partial_apply_callee_guaranteed
+// CHECK:  [[CONTEXT:%.*]] = call {{.*}}@swift_rt_swift_allocObject
+// CHECK:  store
+// CHECK:  [[CLOSURE:%.*]] = insertvalue {{.*}}@_T0Ta.20{{.*}}, {{.*}}[[CONTEXT]], 1
+// CHECK: ret {{.*}}[[CLOSURE]]
+
+sil @objc_partial_apply_callee_guaranteed : $@convention(thin) ObjCClass -> @callee_guaranteed Int -> () {
+entry(%c : $ObjCClass):
+  %m = objc_method %c : $ObjCClass, #ObjCClass.method!1.foreign : (ObjCClass) -> (Int) -> (), $@convention(objc_method) (Int, ObjCClass) -> ()
+  %p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Int, ObjCClass) -> ()
+  return %p : $@callee_guaranteed Int -> ()
+}
+
+// CHECK-LABEL: define {{.*}}swiftcc void @_T0Ta.20(i64, %swift.refcounted* swiftself)
+// CHECK: entry:
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK:   call {{.*}}@objc_msgSend
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK-LABEL: define {{.*}}@objc_partial_apply_2_callee_guaranteed
+// CHECK:  [[CONTEXT:%.*]] = call {{.*}}@swift_rt_swift_allocObject
+// CHECK: store
+// CHECK:  [[CLOSURE:%.*]] = insertvalue {{.*}}@_T0Ta.23{{.*}}, {{.*}}[[CONTEXT]], 1
+// CHECK: ret {{.*}}[[CLOSURE]]
+
+sil @objc_partial_apply_2_callee_guaranteed : $@convention(thin) Gizmo -> @callee_guaranteed (Fob) -> () {
+entry(%c : $Gizmo):
+  %m = objc_method %c : $Gizmo, #Gizmo.test!1.foreign : (Gizmo) -> (Fob) -> (), $@convention(objc_method) (Fob,  Gizmo) -> ()
+  %p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Fob,  Gizmo) -> ()
+  return %p : $@callee_guaranteed (Fob) -> ()
+}
+
+// CHECK-LABEL: define {{.*}}swiftcc void @_T0Ta.23(i64, i64, i64, %swift.refcounted* swiftself)
+// CHECK: entry:
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK:   call {{.*}}@objc_msgSend
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK:   ret void
+// CHECK: }
diff --git a/test/IRGen/protocol_resilience.sil b/test/IRGen/protocol_resilience.sil
index c3b86ab..ddfbb61 100644
--- a/test/IRGen/protocol_resilience.sil
+++ b/test/IRGen/protocol_resilience.sil
@@ -296,7 +296,11 @@
 
 // CHECK-LABEL: define{{( protected)?}} i8** @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWa()
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWG, %swift.type* null, i8** null)
+// CHECK-NEXT:    %conditional.tables = alloca %swift.witness_table_slice
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:    store [[WORD:i(32|64)]] 0, [[WORD:i(32|64)]]* [[COUNT_PTR]]
+// CHECK-NEXT:    [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:    [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWG, %swift.type* null, i8** [[INSTANTIATION_ARGS]])
 // CHECK-NEXT:    ret i8** [[WTABLE]]
 
 
diff --git a/test/IRGen/sil_linkage.sil b/test/IRGen/sil_linkage.sil
index f0f3149..0fdbe7a 100644
--- a/test/IRGen/sil_linkage.sil
+++ b/test/IRGen/sil_linkage.sil
@@ -3,7 +3,7 @@
 sil_stage canonical
 
 // CHECK: define{{( protected)?}} swiftcc void @public_fragile_function_test() {{.*}} {
-// CHECK: define{{( protected)?}} internal swiftcc void @public_transparent_fragile_function_test() {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @public_transparent_fragile_function_test() {{.*}} {
 // CHECK: define{{( protected)?}} swiftcc void @public_transparent_function_test() {{.*}} {
 // CHECK: define{{( hidden)?}} swiftcc void @hidden_fragile_function_test() {{.*}} {
 // CHECK: define linkonce_odr hidden swiftcc void @shared_fragile_function_test() {{.*}} {
diff --git a/test/IRGen/superclass_constraint.swift b/test/IRGen/superclass_constraint.swift
index 620b1e7..1466e37 100644
--- a/test/IRGen/superclass_constraint.swift
+++ b/test/IRGen/superclass_constraint.swift
@@ -8,9 +8,9 @@
   // CHECK-LABEL: define{{.*}} @_T021superclass_constraint3CVCCACyxGycfc
   public init() {
     // CHECK: [[A:%.*]] = alloca %T21superclass_constraint3CVCC*
-    // CHECK-NOT: ret
+    // CHECK-NOT: ret %T21superclass_constraint3CVCC*
     // CHECK: store %T21superclass_constraint3CVCC* %0, %T21superclass_constraint3CVCC** [[A]]
-    // CHECK: ret
+    // CHECK: ret %T21superclass_constraint3CVCC*
     var a = self
   }
 }
diff --git a/test/IRGen/typed_boxes.sil b/test/IRGen/typed_boxes.sil
index 8999242..502d614 100644
--- a/test/IRGen/typed_boxes.sil
+++ b/test/IRGen/typed_boxes.sil
@@ -7,15 +7,13 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_a
 sil @pod_box_8_8_a : $@convention(thin) () -> () {
 entry:
-  // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD:i[0-9]+]] 24, [[WORD]] 7)
+  // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], i32 0, i32 2), [[WORD:i[0-9]+]] [[POD_8_8_SIZE:[0-9]+]], [[WORD]] 7)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
-  // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
-  // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
-  // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
-  // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+  // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+  // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
   // CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
   %b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
-  // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+  // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
   dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
   return undef : $()
 }
@@ -23,15 +21,13 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_b
 sil @pod_box_8_8_b : $@convention(thin) () -> () {
 entry:
-  // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
+  // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], i32 0, i32 2), [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
-  // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
-  // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
-  // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
-  // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+  // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+  // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
   // CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to double*
   %b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>, 0
-  // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+  // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
   dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
   return undef : $()
 }
@@ -46,7 +42,7 @@
 entry:
   // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_32_32_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 64, [[WORD]] 31)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <OverAligned>
-  // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[20 x i8\], \[32 x i8\] \}>]]*
+  // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[24 x i8\], \[32 x i8\] \}>]]*
   // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[16 x i8\], \[32 x i8\] \}>]]*
   // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_32_32_LAYOUT]], [[POD_32_32_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
   // CHECK: [[BOX_DATA_1:%.*]] = bitcast [32 x i8]* [[BOX_DATA]] to %T11typed_boxes11OverAlignedV*
@@ -65,7 +61,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @rc_box_a
 sil @rc_box_a : $@convention(thin) () -> () {
 entry:
-  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
   // CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <C>
   // CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1CC**
@@ -78,7 +74,7 @@
 sil @rc_box_b : $@convention(thin) () -> () {
 entry:
   // TODO: Should reuse metadata
-  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 12, [[WORD]] 3)
   // CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <D>
   // CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1DC**
@@ -90,7 +86,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @unknown_rc_box
 sil @unknown_rc_box : $@convention(thin) () -> () {
 entry:
-  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+  // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
   // CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>
   %b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>, 0
@@ -158,10 +154,8 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc i64 @proj_box
 sil @proj_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Builtin.Int64>) -> Builtin.Int64 {
 entry(%0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>):
-  // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
-  // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
-  // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
-  // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+  // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+  // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
   // CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
   %p = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
   // CHECK: [[R:%.*]] = load i64, i64* [[BOX_DATA_1]]
diff --git a/test/IRGen/vector_reduction.swift b/test/IRGen/vector_reduction.swift
index aa93041..8ebc383 100644
--- a/test/IRGen/vector_reduction.swift
+++ b/test/IRGen/vector_reduction.swift
@@ -7,7 +7,7 @@
 
 // We were missing target transform info and not vectorizing the loop below.
 
-// CHECK: xor <2 x i64>
+// CHECK: xor <{{(2|4|8)}} x i64>
 
 public func f(a: UnsafePointer<Int>, b: UnsafePointer<Int>, count: Int) -> Int {
   var c = 0
diff --git a/test/IRGen/witness_method.sil b/test/IRGen/witness_method.sil
index 9188def..3669da7 100644
--- a/test/IRGen/witness_method.sil
+++ b/test/IRGen/witness_method.sil
@@ -63,7 +63,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
 // CHECK: entry:
 // CHECK:   [[METADATA:%.*]] = call %swift.type* @_T014witness_method6SyncUpVMa(%swift.type* %T)
-// CHECK:   [[WTABLE:%.*]] = call i8** @_T014witness_method6SyncUpVyxGAA7SynergyAAWa(%swift.type* [[METADATA]])
+// CHECK:   [[WTABLE:%.*]] = call i8** @_T014witness_method6SyncUpVyxGAA7SynergyAAWa(%swift.type* [[METADATA]], i8*** undef, {{i32|i64}} 0)
 // CHECK:   [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 1
 // CHECK:   [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
 // CHECK:   [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
diff --git a/test/Inputs/conditional_conformance_basic_conformances.swift b/test/Inputs/conditional_conformance_basic_conformances.swift
new file mode 100644
index 0000000..e5b2681
--- /dev/null
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -0,0 +1,336 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+  func normal()
+  func generic<T: P3>(_: T)
+}
+public protocol P2 {}
+public protocol P3 {}
+
+public struct IsP2: P2 {}
+public struct IsP3: P3 {}
+
+
+public struct Single<A> {}
+extension Single: P1 where A: P2 {
+  public func normal() {}
+  public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Single.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlAaEP6normalyyFTW(%T42conditional_conformance_basic_conformances6SingleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %0 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances6SingleVA2A2P2RzlE6normalyyF(%swift.type* [[A]], i8** [[A_P2]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness method for Single.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T42conditional_conformance_basic_conformances6SingleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %1 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances6SingleVA2A2P2RzlE7genericyqd__AA2P3Rd__lF(%swift.opaque* noalias nocapture %0, %swift.type* [[A]], %swift.type* %"\CF\84_1_0", i8** [[A_P2]], i8** %"\CF\84_1_0.P3")
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+public func single_generic<T: P2>(_: T.Type) {
+  takes_p1(Single<T>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances14single_genericyxmAA2P2RzlF(%swift.type*, %swift.type* %T, i8** %T.P2) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVMa(%swift.type* %T)
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[T_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** %T.P2, i8*** [[T_P2_PTR]], align 8
+// CHECK-NEXT:    [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Single_TYPE]], %swift.type* [[Single_TYPE]], i8** [[Single_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// Witness table accessor for Single : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT:    store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:    store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:    [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT:    ret i8** [[TABLE]]
+// CHECK-NEXT:  }
+
+
+public func single_concrete() {
+  takes_p1(Single<IsP2>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances15single_concreteyyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa()
+// CHECK-NEXT:    [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWl()
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Single_TYPE]], %swift.type* [[Single_TYPE]], i8** [[Single_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+
+// Lazy witness table accessor for the concrete Single<IsP2> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWl() #1 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa()
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP2VAA0F0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+
+// CHECK-NEXT:    [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    store atomic i8** [[Single_P1]], i8*** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %6 = phi i8** [ [[CACHE]], %entry ], [ [[Single_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %6
+// CHECK-NEXT:  }
+
+
+public struct Double<B, C> {}
+extension Double: P1 where B: P2, C: P3 {
+  public func normal() {}
+  public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Double.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlAaEP6normalyyFTW(%T42conditional_conformance_basic_conformances6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[B_P2_i8star:%.*]] = load i8*, i8** [[B_P2_PTR]], align 8
+// CHECK-NEXT:    [[B_P2:%.*]] = bitcast i8* [[B_P2_i8star]] to i8**
+
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT:    [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
+
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %0 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT:    [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVA2A2P2RzAA2P3R_rlE6normalyyF(%swift.type* [[B]], %swift.type* [[C]], i8** [[B_P2]], i8** [[C_P3]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness method for Double.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlAaEP7genericyqd__AaGRd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T42conditional_conformance_basic_conformances6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[B_P2_i8star:%.*]] = load i8*, i8** [[B_P2_PTR]], align 8
+// CHECK-NEXT:    [[B_P2:%.*]] = bitcast i8* [[B_P2_i8star]] to i8**
+
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT:    [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
+
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %1 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT:    [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVA2A2P2RzAA2P3R_rlE7genericyqd__AaERd__lF(%swift.opaque* noalias nocapture %0, %swift.type* [[B]], %swift.type* [[C]], %swift.type* %"\CF\84_1_0", i8** [[B_P2]], i8** [[C_P3]], i8** %"\CF\84_1_0.P3")
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+
+public func double_generic_generic<U: P2, V: P3>(_: U.Type, _: V.Type) {
+  takes_p1(Double<U, V>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances015double_generic_F0yxm_q_mtAA2P2RzAA2P3R_r0_lF(%swift.type*, %swift.type*, %swift.type* %U, %swift.type* %V, i8** %U.P2, i8** %V.P3) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVMa(%swift.type* %U, %swift.type* %V)
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** %U.P2, i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** %V.P3, i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness table accessor for Double : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT:    store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:    store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:    [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT:    ret i8** [[TABLE]]
+// CHECK-NEXT:  }
+
+
+public func double_generic_concrete<X: P2>(_: X.Type) {
+  takes_p1(Double<X, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances23double_generic_concreteyxmAA2P2RzlF(%swift.type*, %swift.type* %X, i8** %X.P2) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVMa(%swift.type* %X, %swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T042conditional_conformance_basic_conformances4IsP3VMf, i32 0, i32 1) to %swift.type*))
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** %X.P2, i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* %1, i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+public func double_concrete_concrete() {
+  takes_p1(Double<IsP2, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances016double_concrete_F0yyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa()
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWl()
+// CHECK-NEXT:    call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// Lazy witness table accessor for the concrete Double<IsP2, IsP3> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWl() #1 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa()
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP2VAA0F0AAWP, i32 0, i32 0), i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT:    store atomic i8** [[Double_P1]], i8*** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %7 = phi i8** [ [[CACHE]], %entry ], [ [[Double_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %7
+// CHECK-NEXT:  }
+
+
+// # Witness table instantiators
+
+// witness table instantiator for Single : P1
+
+// CHECK-LABEL: define internal void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT:    [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT:    [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[COUNT]], 1
+// CHECK-NEXT:    br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK:       cont:
+// CHECK-NEXT:    [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT:    [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT:    [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
+// CHECK-NEXT:    [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
+
+// CHECK-NEXT:    ret void
+
+// CHECK:       bad_witness_table_count:
+// CHECK-NEXT:    call void @llvm.trap()
+// CHECK-NEXT:    unreachable
+// CHECK-NEXT:  }
+
+// witness table instantiator for Double : P1
+
+// CHECK-LABEL: define internal void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT:    [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT:    [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[COUNT]], 2
+// CHECK-NEXT:    br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK:       cont:
+// CHECK-NEXT:    [[B_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT:    [[B_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT:    [[B_P2:%.*]] = load i8**, i8*** [[B_P2_SRC]], align 8
+// CHECK-NEXT:    [[CAST_B_P2_DEST:%.*]] = bitcast i8** [[B_P2_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[B_P2]], i8*** [[CAST_B_P2_DEST]], align 8
+
+// CHECK-NEXT:    [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
+// CHECK-NEXT:    [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
+// CHECK-NEXT:    [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
+// CHECK-NEXT:    [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
+
+// CHECK-NEXT:    ret void
+
+// CHECK:       bad_witness_table_count:
+// CHECK-NEXT:    call void @llvm.trap()
+// CHECK-NEXT:    unreachable
+// CHECK-NEXT:  }
+
diff --git a/test/Inputs/conditional_conformance_subclass.swift b/test/Inputs/conditional_conformance_subclass.swift
new file mode 100644
index 0000000..96d0525
--- /dev/null
+++ b/test/Inputs/conditional_conformance_subclass.swift
@@ -0,0 +1,209 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+  func normal()
+  func generic<T: P3>(_: T)
+}
+public protocol P2 {}
+public protocol P3 {}
+
+public struct IsP2: P2 {}
+
+public class Base<A> {}
+extension Base: P1 where A: P2 {
+  public func normal() {}
+  public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Base.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP6normalyyFTW(%T32conditional_conformance_subclass4BaseC.0** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
+// CHECK-NEXT:    [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.0*, %T32conditional_conformance_subclass4BaseC.0** %0
+// CHECK-NEXT:    [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.0* [[SELF]] to %swift.refcounted*
+// CHECK-NEXT:    [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE6normalyyF(i8** %"\CF\84_0_0.P2", %T32conditional_conformance_subclass4BaseC.0* swiftself [[SELF]])
+// CHECK-NEXT:    call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.0*)*)(%T32conditional_conformance_subclass4BaseC.0* [[SELF]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness method for Base.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
+// CHECK-NEXT:    [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.1*, %T32conditional_conformance_subclass4BaseC.1** %1, align 8
+// CHECK-NEXT:    [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.1* [[SELF]] to %swift.refcounted*
+// CHECK-NEXT:    [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE7genericyqd__AA2P3Rd__lF(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1* swiftself [[SELF]])
+// CHECK-NEXT:    call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.1*)*)(%T32conditional_conformance_subclass4BaseC.1* [[SELF]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+
+public class SubclassGeneric<T>: Base<T> {}
+public class SubclassConcrete: Base<IsP2> {}
+public class SubclassGenericConcrete: SubclassGeneric<IsP2> {}
+
+public func subclassgeneric_generic<T: P2>(_: T.Type) {
+  takes_p1(SubclassGeneric<T>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass23subclassgeneric_genericyxmAA2P2RzlF(%swift.type*, %swift.type* %T, i8** %T.P2) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCMa(%swift.type* %T)
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[T_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** %T.P2, i8*** [[T_P2_PTR]], align 8
+// CHECK-NEXT:    [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness table accessor for Base : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT:    store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT:    store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT:    [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT:    ret i8** [[TABLE]]
+// CHECK-NEXT:  }
+
+public func subclassgeneric_concrete() {
+  takes_p1(SubclassGeneric<IsP2>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass24subclassgeneric_concreteyyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa()
+// CHECK-NEXT:    [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl()
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// Lazy witness table accessor for the concrete SubclassGeneric<IsP2> : Base.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl() #2 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa()
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %6
+// CHECK-NEXT:  }
+
+public func subclassconcrete() {
+  takes_p1(SubclassConcrete.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass16subclassconcreteyyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[SubclassConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass16SubclassConcreteCMa()
+// CHECK-NEXT:    [[SubclassConcrete_P1:%.*]] = call i8** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl()
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassConcrete_TYPE]], %swift.type* [[SubclassConcrete_TYPE]], i8** [[SubclassConcrete_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl() #2 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[SubclassConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass16SubclassConcreteCMa()
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %6
+// CHECK-NEXT:  }
+
+public func subclassgenericconcrete() {
+  takes_p1(SubclassGenericConcrete.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass23subclassgenericconcreteyyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[SubclassGenericConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass23SubclassGenericConcreteCMa()
+// CHECK-NEXT:    [[SubclassGenericConcrete_P1:%.*]] = call i8** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl()
+// CHECK-NEXT:    call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGenericConcrete_TYPE]], %swift.type* [[SubclassGenericConcrete_TYPE]], i8** [[SubclassGenericConcrete_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl() #2 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[SubclassGenericConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass23SubclassGenericConcreteCMa()
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT:    [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT:    store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %6
+// CHECK-NEXT:  }
+
+
+// witness tabel instantiation function for Base : P1
+
+// CHECK-LABEL: define internal void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT:    [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT:    [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[COUNT]], 1
+// CHECK-NEXT:    br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK:       cont:
+// CHECK-NEXT:    [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT:    [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT:    [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
+// CHECK-NEXT:    [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
+// CHECK-NEXT:    ret void
+
+// CHECK:       bad_witness_table_count:
+// CHECK-NEXT:    call void @llvm.trap()
+// CHECK-NEXT:    unreachable
+// CHECK-NEXT:  }
+
+
diff --git a/test/Inputs/conditional_conformance_with_assoc.swift b/test/Inputs/conditional_conformance_with_assoc.swift
new file mode 100644
index 0000000..63af461
--- /dev/null
+++ b/test/Inputs/conditional_conformance_with_assoc.swift
@@ -0,0 +1,263 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+  associatedtype AT1
+
+  func normal()
+  func generic<T: P3>(_: T)
+}
+public protocol P2 {
+  associatedtype AT2: P3
+}
+public protocol P3 {
+  associatedtype AT3
+}
+
+public struct Nothing {}
+
+public struct IsP2: P2 {
+  public typealias AT2 = IsP3
+}
+public struct IsP3: P3 {
+  public typealias AT3 = Nothing
+}
+
+public struct IsAlsoP2: P2 {
+  public typealias AT2 = IsBoth
+}
+public struct IsBoth: P2, P3 {
+  public typealias AT2 = HoldsP3
+  public typealias AT3 = Nothing
+}
+public struct HoldsP3: P3 {
+  public typealias AT3 = IsP3
+}
+
+public struct Double<B: P2, C> {}
+extension Double: P1 where B.AT2: P2, C: P3, B.AT2.AT2.AT3: P3 {
+  public typealias AT1 = C
+  public func normal() {}
+  public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Double.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlAaEP6normalyyFTW(%T34conditional_conformance_with_assoc6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[C_P3:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_1.P3" = bitcast i8* [[C_P3]] to i8**
+
+// CHECK-NEXT:    [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT:    [[B_AT2_P2:%.*]] = load i8*, i8** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.AT2.P2" = bitcast i8* [[B_AT2_P2]] to i8**
+
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -3
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
+
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %0 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT:    [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_WT_ARRAY:%.*]] = bitcast %swift.type* %Self to i8***
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[SELF_AS_WT_ARRAY]], i64 4
+// CHECK-NEXT:    %"\CF\84_0_0.P2" = load i8**, i8*** [[B_P2_PTR]], align 8
+
+// CHECK-NEXT:    call swiftcc void @_T034conditional_conformance_with_assoc6DoubleVA2A2P3R_AA2P23AT2RpzAadF_AfaEP3AT3RPzrlE6normalyyF(%swift.type* %"\CF\84_0_0", %swift.type* %"\CF\84_0_1", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_0_1.P3", i8** %"\CF\84_0_0.AT2.P2", i8** %"\CF\84_0_0.AT2.AT2.AT3.P3")
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// witness method for Double.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlAaEP7genericyqd__AaFRd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T34conditional_conformance_with_assoc6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT:    [[C_P3:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_1.P3" = bitcast i8* [[C_P3]] to i8**
+
+// CHECK-NEXT:    [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT:    [[B_AT2_P2:%.*]] = load i8*, i8** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.AT2.P2" = bitcast i8* [[B_AT2_P2]] to i8**
+
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -3
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT:    %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
+
+// CHECK-NEXT:    [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
+// CHECK-NEXT:    [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %1 to i8*
+// CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT:    [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT:    [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT:    [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT:    [[SELF_AS_WT_ARRAY:%.*]] = bitcast %swift.type* %Self to i8***
+// CHECK-NEXT:    [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[SELF_AS_WT_ARRAY]], i64 4
+// CHECK-NEXT:    %"\CF\84_0_0.P2" = load i8**, i8*** [[B_P2_PTR]], align 8
+
+// CHECK-NEXT:    call swiftcc void @_T034conditional_conformance_with_assoc6DoubleVA2A2P3R_AA2P23AT2RpzAadF_AfaEP3AT3RPzrlE7genericyqd__AaDRd__lF(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_0_0", %swift.type* %"\CF\84_0_1", %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_0_1.P3", i8** %"\CF\84_1_0.P3", i8** %"\CF\84_0_0.AT2.P2", i8** %"\CF\84_0_0.AT2.AT2.AT3.P3")
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+
+public func generic_generic<T: P2, U>(_: T.Type, _: U.Type)
+  where T.AT2: P2, U: P3, T.AT2.AT2.AT3: P3
+{
+  takes_p1(Double<T, U>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc08generic_E0yxm_q_mtAA2P2RzAA2P3R_AaC3AT2RpzAadE_AeaCP3AT3RPzr0_lF(%swift.type*, %swift.type*, %swift.type* %T, %swift.type* %U, i8** %T.P2, i8** %U.P3, i8** %T.AT2.P2, i8** %T.AT2.AT2.AT3.P3) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* %T, %swift.type* %U, i8** %T.P2)
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** %U.P3, i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** %T.AT2.P2, i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT:    store i8** %T.AT2.AT2.AT3.P3, i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT:    call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+public func generic_concrete<T: P2>(_: T.Type)
+  where T.AT2: P2, T.AT2.AT2.AT3: P3
+{
+  takes_p1(Double<T, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc16generic_concreteyxmAA2P2RzAaC3AT2RpzAA2P3AD_AdaCP3AT3RPzlF(%swift.type*, %swift.type* %T, i8** %T.P2, i8** %T.AT2.P2, i8** %T.AT2.AT2.AT3.P3) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* %T, %swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T034conditional_conformance_with_assoc4IsP3VMf, i32 0, i32 1) to %swift.type*), i8** %T.P2)
+
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** %T.AT2.P2, i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT:    store i8** %T.AT2.AT2.AT3.P3, i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT:    call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+
+public func concrete_generic<U>(_: U.Type)
+  where U: P3
+{
+  takes_p1(Double<IsAlsoP2, U>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc16concrete_genericyxmAA2P3RzlF(%swift.type*, %swift.type* %U, i8** %U.P3) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT:  [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T034conditional_conformance_with_assoc8IsAlsoP2VMf, i32 0, i32 1) to %swift.type*), %swift.type* %U, i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc8IsAlsoP2VAA0G0AAWP, i32 0, i32 0))
+// CHECK-NEXT:  [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:  [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:  store i8** %U.P3, i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT:  [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:  store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc6IsBothVAA2P2AAWP, i32 0, i32 0), i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:  [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT:  store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT:  [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT:  call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT:  ret void
+// CHECK-NEXT:}
+
+
+public func concrete_concrete() {
+  takes_p1(Double<IsAlsoP2, IsP3>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc09concrete_E0yyF() #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %0 = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa() #10
+// CHECK-NEXT:    %1 = call i8** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWl() #10
+// CHECK-NEXT:    call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* %0, %swift.type* %0, i8** %1)
+// CHECK-NEXT:    ret void
+// CHECK-NEXT: }
+
+// Lazy witness table accessor for the concrete Double<IsAlsoP2, IsP3> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWl() #1 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT:    [[CACHE:%.*]] = load i8**, i8*** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWL, align 8
+// CHECK-NEXT:    [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT:    br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK:       cacheIsNull:
+// CHECK-NEXT:    [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa() #10
+// CHECK-NEXT:    [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT:    [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT:    store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT:    store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc6IsBothVAA2P2AAWP, i32 0, i32 0), i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT:    store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT:    [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT:    store atomic i8** [[Double_P1]], i8*** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWL release, align 8
+// CHECK-NEXT:    br label %cont
+
+// CHECK:       cont:
+// CHECK-NEXT:    %8 = phi i8** [ [[CACHE]], %entry ], [ [[Double_P1]], %cacheIsNull ]
+// CHECK-NEXT:    ret i8** %8
+// CHECK-NEXT:  }
+
+
+
+// witness table instantiator for Double : P1
+
+// CHECK-LABEL: define internal void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT:    [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT:    [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT:    [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT:    [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[COUNT]],
+// CHECK-NEXT:    br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK:       cont:
+// CHECK-NEXT:    [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT:    [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT:    [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
+// CHECK-NEXT:    [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
+
+// CHECK-NEXT:    [[B_AT2_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
+// CHECK-NEXT:    [[B_AT2_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
+// CHECK-NEXT:    [[B_AT2_P2:%.*]] = load i8**, i8*** [[B_AT2_P2_SRC]], align 8
+// CHECK-NEXT:    [[CAST_B_AT2_P2_DEST:%.*]] = bitcast i8** [[B_AT2_P2_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[B_AT2_P2]], i8*** [[CAST_B_AT2_P2_DEST]], align 8
+
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 2
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -3
+// CHECK-NEXT:    [[B_AT2_AT2_AT3_P3:%.*]] = load i8**, i8*** [[B_AT2_AT2_AT3_P3_SRC]], align 8
+// CHECK-NEXT:    [[CAST_B_AT2_AT2_AT3_P3_DEST:%.*]] = bitcast i8** [[B_AT2_AT2_AT3_P3_DEST]] to i8***
+// CHECK-NEXT:    store i8** [[B_AT2_AT2_AT3_P3]], i8*** [[CAST_B_AT2_AT2_AT3_P3_DEST]], align 8
+
+// CHECK-NEXT:    ret void
+
+// CHECK:       bad_witness_table_count:
+// CHECK-NEXT:    call void @llvm.trap()
+// CHECK-NEXT:    unreachable
+// CHECK-NEXT:  }
+
diff --git a/test/Interpreter/conditional_conformances.swift b/test/Interpreter/conditional_conformances.swift
new file mode 100644
index 0000000..8c686dc
--- /dev/null
+++ b/test/Interpreter/conditional_conformances.swift
@@ -0,0 +1,35 @@
+// RUN: %empty-directory(%t)
+// The file that's `main` needs to be called that.
+// RUN: cp %s %t/main.swift
+// RUN: %target-build-swift -D basic %t/main.swift %S/../Inputs/conditional_conformance_basic_conformances.swift -o %t/basic && %target-run %t/basic
+// RUN: %target-build-swift -D with_assoc %t/main.swift %S/../Inputs/conditional_conformance_with_assoc.swift -o %t/with_assoc && %target-run %t/with_assoc
+// RUN: %target-build-swift -D subclass %t/main.swift %S/../Inputs/conditional_conformance_subclass.swift -o %t/subclass && %target-run %t/subclass
+
+// REQUIRES: executable_test
+
+// Call the various functions from each of the IRGen conditional conformance
+// tests. These can't be put in the file themselves because that changes it from
+// being treated as a library to an executable.
+
+#if basic
+single_generic(IsP2.self)
+single_concrete()
+
+double_generic_generic(IsP2.self, IsP3.self)
+double_generic_concrete(IsP2.self)
+double_concrete_concrete()
+
+#elseif with_assoc
+generic_generic(IsAlsoP2.self, IsP3.self)
+generic_concrete(IsAlsoP2.self)
+concrete_generic(IsP3.self)
+concrete_concrete()
+
+#elseif subclass
+subclassgeneric_generic(IsP2.self)
+subclassgeneric_concrete()
+subclassconcrete()
+subclassgenericconcrete()
+#endif
+
+
diff --git a/test/Interpreter/conditional_conformances_modules.swift b/test/Interpreter/conditional_conformances_modules.swift
new file mode 100644
index 0000000..b5c94ae
--- /dev/null
+++ b/test/Interpreter/conditional_conformances_modules.swift
@@ -0,0 +1,91 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift-dylib(%t/libBasic.%target-dylib-extension) %S/../Inputs/conditional_conformance_basic_conformances.swift -module-name Basic -emit-module -emit-module-path %t/Basic.swiftmodule
+// RUN: %target-build-swift-dylib(%t/libWithAssoc.%target-dylib-extension) %S/../Inputs/conditional_conformance_with_assoc.swift -module-name WithAssoc -emit-module -emit-module-path %t/WithAssoc.swiftmodule
+// FIXME: currently fails due to incorrect modeling of type parameters in inherited conformances.
+// %target-build-swift-dylib(%t/libSubclass.%target-dylib-extension) %S/../Inputs/conditional_conformance_subclass.swift -module-name Subclass -emit-module -emit-module-path %t/Subclass.swiftmodule
+// RUN: %target-build-swift -I%t -L%t -lBasic -lWithAssoc %s -o %t/conditional_conformances_modules -Xlinker -rpath -Xlinker %t
+// RUN: %target-run %t/conditional_conformances_modules %t/libBasic.%target-dylib-extension %t/libWithAssoc.%target-dylib-extension
+
+// REQUIRES: executable_test
+// FIXME: seems to fail on 32-bit simulator?
+// REQUIRES: OS=macosx || OS=linux
+
+import Basic
+import WithAssoc
+// FIXME: see above
+// import Subclass
+
+
+public func basic_single_generic<T: Basic.P2>(_: T.Type) {
+  Basic.takes_p1(Basic.Single<T>.self)
+}
+public func basic_single_concrete() {
+  Basic.takes_p1(Basic.Single<Basic.IsP2>.self)
+}
+public func basic_double_generic_generic<U: Basic.P2, V: Basic.P3>(_: U.Type, _: V.Type) {
+  Basic.takes_p1(Basic.Double<U, V>.self)
+}
+public func basic_double_generic_concrete<X: Basic.P2>(_: X.Type) {
+  Basic.takes_p1(Basic.Double<X, Basic.IsP3>.self)
+}
+public func basic_double_concrete_concrete() {
+  Basic.takes_p1(Basic.Double<Basic.IsP2, Basic.IsP3>.self)
+}
+
+
+public func with_assoc_generic_generic<T: WithAssoc.P2, U>(_: T.Type, _: U.Type)
+  where T.AT2: WithAssoc.P2, U: WithAssoc.P3, T.AT2.AT2.AT3: WithAssoc.P3
+{
+  WithAssoc.takes_p1(WithAssoc.Double<T, U>.self)
+}
+public func with_assoc_generic_concrete<T: WithAssoc.P2>(_: T.Type)
+  where T.AT2: WithAssoc.P2, T.AT2.AT2.AT3: WithAssoc.P3
+{
+  WithAssoc.takes_p1(WithAssoc.Double<T, WithAssoc.IsP3>.self)
+}
+public func with_assoc_concrete_generic<U>(_: U.Type)
+  where U: WithAssoc.P3
+{
+  WithAssoc.takes_p1(WithAssoc.Double<WithAssoc.IsAlsoP2, U>.self)
+}
+public func with_assoc_concrete_concrete() {
+  WithAssoc.takes_p1(WithAssoc.Double<WithAssoc.IsAlsoP2, WithAssoc.IsP3>.self)
+}
+
+/*
+FIXME: see above
+public func subclass_subclassgeneric_generic<T: Subclass.P2>(_: T.Type) {
+  Subclass.takes_p1(Subclass.SubclassGeneric<T>.self)
+}
+public func subclass_subclassgeneric_concrete() {
+  Subclass.takes_p1(Subclass.SubclassGeneric<Subclass.IsP2>.self)
+}
+public func subclass_subclassconcrete() {
+  Subclass.takes_p1(Subclass.SubclassConcrete.self)
+}
+public func subclass_subclassgenericconcrete() {
+  Subclass.takes_p1(Subclass.SubclassGenericConcrete.self)
+}
+*/
+
+
+basic_single_generic(Basic.IsP2.self)
+basic_single_concrete()
+basic_double_generic_generic(Basic.IsP2.self, Basic.IsP3.self)
+basic_double_generic_concrete(Basic.IsP2.self)
+basic_double_concrete_concrete()
+
+
+with_assoc_generic_generic(WithAssoc.IsAlsoP2.self, WithAssoc.IsP3.self)
+with_assoc_generic_concrete(WithAssoc.IsAlsoP2.self)
+with_assoc_concrete_generic(WithAssoc.IsP3.self)
+with_assoc_concrete_concrete()
+
+
+/*
+FIXME: see above
+subclass_subclassgeneric_generic(Subclass.IsP2.self)
+subclass_subclassgeneric_concrete()
+subclass_subclassconcrete()
+subclass_subclassgenericconcrete()
+*/
diff --git a/test/Interpreter/conditional_conformances_smoke.swift b/test/Interpreter/conditional_conformances_smoke.swift
new file mode 100644
index 0000000..0943d8b
--- /dev/null
+++ b/test/Interpreter/conditional_conformances_smoke.swift
@@ -0,0 +1,89 @@
+// RUN: %target-run-simple-swift | %FileCheck %s
+
+// REQUIRES: executable_test
+
+// Test fails in optimized mode. rdar://35492657
+// REQUIRES: swift_test_mode_optimize_none
+
+// Smoke test to see that various conditional conformances correctly execute
+
+protocol P1 {
+  func method1()
+}
+var isp1_count = 0
+struct IsP1: P1 {
+  var id: Int
+  init() {
+    id = isp1_count
+    isp1_count += 1
+  }
+  func method1() {
+    print("IsP1", id)
+  }
+}
+protocol P2 {
+  func method2()
+}
+protocol P3 {
+  func method3()
+}
+protocol P4: P1 {
+  func method4()
+}
+
+protocol Assoc { associatedtype AT }
+
+func takes_P2<X: P2>(_ x: X) {
+  x.method2()
+}
+
+struct NoRecur<T> {
+  var x: T
+}
+extension NoRecur: P2 where T: P1 {
+  func method2() {
+    print("NoRecur")
+    x.method1()
+  }
+}
+
+var noRecur = NoRecur(x: IsP1())
+print("noRecur.method2()")
+noRecur.method2()
+// CHECK-LABEL: noRecur.method2()
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 0
+
+print("takes_P2(NoRecur(...))")
+takes_P2(NoRecur(x: IsP1()))
+// CHECK-LABEL: takes_P2(NoRecur(...))
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 1
+
+struct Recur<T> {
+  var id: Int
+  var x: T
+}
+extension Recur: P2 where T: P2 {
+  func method2() {
+    print("Recur", id)
+    x.method2()
+  }
+}
+
+var recur = Recur(id: 0, x: Recur(id: 1, x: NoRecur(x: IsP1())))
+print("recur.method2()")
+recur.method2()
+// CHECK-LABEL: recur.method2()
+// CHECK-NEXT: Recur 0
+// CHECK-NEXT: Recur 1
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 2
+
+print("takes_P2(Recur(...))")
+takes_P2(Recur(id: 2, x: Recur(id: 3, x: NoRecur(x: IsP1()))))
+// CHECK-LABEL: takes_P2(Recur(...))
+// CHECK-NEXT: Recur 2
+// CHECK-NEXT: Recur 3
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 3
diff --git a/test/Misc/stats_dir_failure_count.swift b/test/Misc/stats_dir_failure_count.swift
new file mode 100644
index 0000000..dbbfb58
--- /dev/null
+++ b/test/Misc/stats_dir_failure_count.swift
@@ -0,0 +1,25 @@
+// Check that a failed process-tree emits nonzero failure counters
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo zzz >%t/other.swift
+// RUN: not %target-swiftc_driver -D BROKEN -j 2 -typecheck -stats-output-dir %t %s %t/other.swift
+// RUN: %utils/process-stats-dir.py --set-csv-baseline %t/stats.csv %t
+// RUN: %FileCheck -input-file %t/stats.csv -check-prefix=FAILURE %s
+// FAILURE: {{"Driver.NumProcessFailures"	1$}}
+// FAILURE: {{"Frontend.NumProcessFailures"	2$}}
+
+// Check that a successful process-tree emits no failure counters
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo 'let x : Int = 1' >%t/other.swift
+// RUN: %target-swiftc_driver -j 2 -typecheck -stats-output-dir %t %s %t/other.swift
+// RUN: %utils/process-stats-dir.py --set-csv-baseline %t/stats.csv %t
+// RUN: %FileCheck -input-file %t/stats.csv -check-prefix=SUCCESS %s
+// SUCCESS-NOT: {{"Driver.NumProcessFailures"}}
+// SUCCESS-NOT: {{"Frontend.NumProcessFailures"}}
+
+func foo() {
+#if BROKEN
+  print(bar)
+#else
+  print(1)
+#endif
+}
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 6bc6a0d..dd3f35f 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -144,7 +144,7 @@
 }
 
 enum ExpressibleByRawTypeNotLiteral : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
-  // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-error@-1 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
+  // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
   case Ladd, Elliott, Sixteenth, Harrison
 }
 
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index dae6ff8..69741eb 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -291,8 +291,10 @@
 func arrayComparison(_ x: [NotEquatable], y: [NotEquatable], p: UnsafeMutablePointer<NotEquatable>) {
   var x = x
   // Don't allow implicit array-to-pointer conversions in operators.
-  let a: Bool = x == y // expected-error{{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists:}}
+  // FIXME: The use of <Self: Equatable> in this diagnostic is awful.
+  let a: Bool = x == y // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+  // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
 
   let _: Bool = p == &x  // Allowed!
 }
diff --git a/test/RemoteAST/structural_types.swift b/test/RemoteAST/structural_types.swift
index 3d0407a..dad61d1 100644
--- a/test/RemoteAST/structural_types.swift
+++ b/test/RemoteAST/structural_types.swift
@@ -54,3 +54,11 @@
 typealias Tuple3 = (x: Int, Float, y: Int.Type)
 printType(Tuple3.self)
 // CHECK: found type: (x: Int, Float, y: Int.Type)
+
+func foo<T>(_: T) {
+  var f = T.self
+  printType(f)
+}
+
+foo() { (x: Int) -> Int in return x }
+// CHECK: found type: (Int) -> Int
diff --git a/test/SIL/Parser/coroutines.sil b/test/SIL/Parser/coroutines.sil
new file mode 100644
index 0000000..9d5bd6b
--- /dev/null
+++ b/test/SIL/Parser/coroutines.sil
@@ -0,0 +1,60 @@
+// RUN: %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @use_int : $@convention(thin) (Int) -> ()
+sil @use_float : $@convention(thin) (Float) -> ()
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+  %0 = tuple ()
+  return %0 : $()
+}
+
+sil @many_signature : $@yield_many () -> (@yields Int, @yields Float) {
+bb0:
+  %0 = tuple ()
+  return %0 : $()
+}
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+  %r = tuple ()
+  return %r : $()
+
+bb2:
+  unwind
+}
+
+sil @yield_many : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+  yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+  %r = tuple ()
+  return %r : $()
+
+bb3:
+  unwind
+
+bb4:
+  unwind
+}
+
+sil @begin_apply : $(Int, Float) -> () {
+bb0(%0 : $Int, %1 : $Float):
+  %coro = function_ref @yield : $@convention(thin) @yield_once (Int, Float) -> (@yields Int, @yields Float)
+  (%int, %float, %token) = begin_apply %coro(%0, %1) : $@convention(thin) @yield_once (Int, Float) -> (@yields Int, @yields Float)
+
+  end_apply %token
+  %r = tuple ()
+  return %r : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_merge.sil b/test/SIL/Parser/coroutines_failure_merge.sil
new file mode 100644
index 0000000..e95cc0d
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_merge.sil
@@ -0,0 +1,21 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+  br bb3
+
+bb2:
+  br bb3
+
+bb3:
+  unreachable
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_unwind_return.sil b/test/SIL/Parser/coroutines_failure_unwind_return.sil
new file mode 100644
index 0000000..c79c645
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_return.sil
@@ -0,0 +1,19 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+  %r = tuple ()
+  return %r : $()
+
+bb2:
+  %r2 = tuple ()
+  return %r2 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_unwind_reuse.sil b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
new file mode 100644
index 0000000..adfe6d6
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
@@ -0,0 +1,25 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+  yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb3
+
+bb2:
+  %r = tuple ()
+  return %r : $()
+
+bb3:
+  unwind
+
+bb4:
+  unwind
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_return.sil b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
new file mode 100644
index 0000000..378e443
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
@@ -0,0 +1,12 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage canonical
+
+import Swift
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+  %0 = tuple ()
+  return %0 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
new file mode 100644
index 0000000..e14b74f
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
@@ -0,0 +1,25 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage canonical
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+  yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+  yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+  %r = tuple ()
+  return %r : $()
+
+bb3:
+  unwind
+
+bb4:
+  unwind
+}
+
diff --git a/test/SIL/Parser/witness_method.sil b/test/SIL/Parser/witness_method.sil
new file mode 100644
index 0000000..51e1ce8
--- /dev/null
+++ b/test/SIL/Parser/witness_method.sil
@@ -0,0 +1,43 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil %s -module-name=witness_tables | %target-sil-opt -assume-parsing-unqualified-ownership-sil -module-name=witness_tables | %FileCheck %s
+
+protocol AssocReqt {
+  func requiredMethod()
+}
+
+struct ConformingAssoc : AssocReqt {
+  func requiredMethod()
+}
+
+// CHECK-LABEL: sil @witness_method : $@convention(witness_method: AssocReqt) (@inout ConformingAssoc) -> () {
+sil @witness_method : $@convention(witness_method: AssocReqt) (@inout ConformingAssoc) -> () {
+bb0(%0 : $*ConformingAssoc):
+  %1 = tuple ()
+  return %1 : $()
+}
+
+// CHECK-LABEL: sil hidden @existential
+sil hidden @existential : $@convention(thin) (@in AssocReqt) -> () {
+bb0(%0 : $*AssocReqt):
+  // CHECK: open_existential_addr
+  %2 = open_existential_addr immutable_access %0 : $*AssocReqt to $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt
+  // CHECK: witness_method $@opened({{.*}}) AssocReqt, #AssocReqt.requiredMethod!1 {{.*}} $@convention(witness_method: AssocReqt)
+  %3 = witness_method $@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt, #AssocReqt.requiredMethod!1 : <Self where Self : AssocReqt> (Self) -> () -> (), %2 : $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+  // CHECK: apply {{.*}} $@convention(witness_method: AssocReqt)
+  %4 = apply %3<@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt>(%2) : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+  destroy_addr %0 : $*AssocReqt
+  %6 = tuple ()
+  return %6 : $()
+}
+
+// CHECK-LABEL: sil hidden @generic
+sil hidden @generic : $@convention(thin) <T where T : AssocReqt> (@in T) -> () {
+bb0(%0 : $*T):
+  // CHECK: witness_method $T, #AssocReqt.requiredMethod!1 {{.*}} $@convention(witness_method: AssocReqt)
+  %2 = witness_method $T, #AssocReqt.requiredMethod!1 : <Self where Self : AssocReqt> (Self) -> () -> () : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+  // CHECK: apply {{.*}} $@convention(witness_method: AssocReqt)
+  %3 = apply %2<T>(%0) : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+  destroy_addr %0 : $*T
+  %5 = tuple ()
+  return %5 : $()
+}
+
diff --git a/test/SIL/whole_module_optimization.swift b/test/SIL/whole_module_optimization.swift
index 01326af..16d24cb 100644
--- a/test/SIL/whole_module_optimization.swift
+++ b/test/SIL/whole_module_optimization.swift
@@ -20,11 +20,11 @@
   // CHECK-NEXT: %1 = struct $Int32 (%0 : $Builtin.Int32)
   // CHECK-NEXT: return %1 : $Int32
 
-  // CHECK-SINGLE-FILE: %0 = function_ref @_T04main7computes5Int32VADycF
-  // CHECK-SINGLE-FILE: %1 = function_ref @_T04main9privateFn33_4704C82F83811927370AA02DFDC75B5ALLs5Int32VyF
-  // CHECK-SINGLE-FILE: %2 = thin_to_thick_function %1
-  // CHECK-SINGLE-FILE: %3 = convert_function %2
-  // CHECK-SINGLE-FILE: %4 = apply %0(%3)
+  // CHECK-SINGLE-FILE: %0 = function_ref @_T04main9privateFn33_4704C82F83811927370AA02DFDC75B5ALLs5Int32VyF
+  // CHECK-SINGLE-FILE: %1 = thin_to_thick_function %0
+  // CHECK-SINGLE-FILE: %2 = convert_function %1
+  // CHECK-SINGLE-FILE: %3 = function_ref @_T04main7computes5Int32VADycF
+  // CHECK-SINGLE-FILE: %4 = apply %3(%2)
   // CHECK-SINGLE-FILE: return %4 : $Int
 
   return compute(privateFn)
diff --git a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
index 2d59069..456b446 100644
--- a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
+++ b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
@@ -93,3 +93,5 @@
 @interface ObjectWithSplitProperty : NSObject
 @property (nonatomic, setter=private_setFlagForSomething:) BOOL flagForSomething;
 @end
+
+extern NSString * __nonnull (^ const __nonnull GlobalBlock)(NSString * __nonnull);
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index 81ed0ab..c81d367 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -50,8 +50,6 @@
 // CHECK-NEXT: end_borrow [[T0]] from [[TEMP]]
 // CHECK-NEXT: destroy_addr [[TEMP]]
 //   Formal access to LHS.
-// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
-// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11OrdinarySubVS2icis
 // CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
 // CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $OrdinarySub
 // CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
@@ -61,6 +59,8 @@
 // CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[BORROWED_ARG_LHS]] : $A
+// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11OrdinarySubVS2icis
 // CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
 // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
 
@@ -139,8 +139,6 @@
 //
 // CHECK:    [[CONT]]:
 //   Formal access to LHS.
-// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
-// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11MutatingSubVS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> () 
 // CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
 // CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
 // CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
@@ -150,6 +148,8 @@
 // CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[BORROWED_ARG_LHS]] : $B
+// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11MutatingSubVS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> () 
 // CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
 // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
 //
diff --git a/test/SILGen/address_only_types.swift b/test/SILGen/address_only_types.swift
index b1d19c2..ae8077d 100644
--- a/test/SILGen/address_only_types.swift
+++ b/test/SILGen/address_only_types.swift
@@ -107,8 +107,8 @@
 func address_only_call_1_ignore_return() {
   // CHECK: bb0:
   some_address_only_function_1()
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
   // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
   // CHECK: apply [[FUNC]]([[TEMP]])
   // CHECK: destroy_addr [[TEMP]]
   // CHECK: dealloc_stack [[TEMP]]
@@ -120,9 +120,9 @@
   // CHECK: bb0([[XARG:%[0-9]+]] : @trivial $*Unloadable):
   // CHECK: debug_value_addr [[XARG]] : $*Unloadable
   some_address_only_function_2(x)
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
   // CHECK: [[X_CALL_ARG:%[0-9]+]] = alloc_stack $Unloadable
   // CHECK: copy_addr [[XARG]] to [initialization] [[X_CALL_ARG]]
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC]]([[X_CALL_ARG]])
   // CHECK: dealloc_stack [[X_CALL_ARG]]
   // CHECK: return
@@ -132,10 +132,10 @@
 func address_only_call_1_in_2() {
   // CHECK: bb0:
   some_address_only_function_2(some_address_only_function_1())
-  // CHECK: [[FUNC2:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
-  // CHECK: [[FUNC1:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
   // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+  // CHECK: [[FUNC1:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC1]]([[TEMP]])
+  // CHECK: [[FUNC2:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC2]]([[TEMP]])
   // CHECK: dealloc_stack [[TEMP]]
   // CHECK: return
@@ -145,8 +145,8 @@
 func address_only_materialize() -> Int {
   // CHECK: bb0:
   return some_address_only_function_1().foo()
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
   // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC]]([[TEMP]])
   // CHECK: [[TEMP_PROJ:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*Unloadable to $*[[OPENED:@opened(.*) Unloadable]]
   // CHECK: [[FOO_METHOD:%[0-9]+]] = witness_method $[[OPENED]], #Unloadable.foo!1
@@ -194,8 +194,8 @@
 func address_only_assignment_from_temp_to_property() {
   // CHECK: bb0:
   global_prop = some_address_only_function_1()
-  // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
   // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+  // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
   // CHECK: apply [[SETTER]]([[TEMP]])
   // CHECK: dealloc_stack [[TEMP]]
 }
@@ -204,9 +204,9 @@
 func address_only_assignment_from_lv_to_property(_ v: Unloadable) {
   // CHECK: bb0([[VARG:%[0-9]+]] : @trivial $*Unloadable):
   // CHECK: debug_value_addr [[VARG]] : $*Unloadable
-  // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
   // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
   // CHECK: copy_addr [[VARG]] to [initialization] [[TEMP]]
+  // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
   // CHECK: apply [[SETTER]]([[TEMP]])
   // CHECK: dealloc_stack [[TEMP]]
   global_prop = v
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index 247e6c9..98f4d4e 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -48,8 +48,8 @@
 // CHECK-LABEL: sil hidden @_T010addressors5test0yyF : $@convention(thin) () -> () {
 func test0() {
 // CHECK: [[A:%.*]] = alloc_stack $A
-// CHECK: [[T0:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[T1:%.*]] = metatype $@thin A.Type
+// CHECK: [[T0:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[AVAL:%.*]] = apply [[T0]]([[T1]]) 
 // CHECK: store [[AVAL]] to [[A]]
   var a = A()
@@ -82,8 +82,8 @@
 
 // CHECK-LABEL: sil hidden @_T010addressors5test1s5Int32VyF : $@convention(thin) () -> Int32
 func test1() -> Int32 {
-// CHECK: [[CTOR:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[T0:%.*]] = metatype $@thin A.Type
+// CHECK: [[CTOR:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[A:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thin A.Type) -> A
 // CHECK: [[ACCESSOR:%.*]] = function_ref @_T010addressors1AVs5Int32VAEcilu : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
 // CHECK: [[PTR:%.*]] = apply [[ACCESSOR]]({{%.*}}, [[A]]) : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
@@ -230,12 +230,12 @@
 // CHECK:   store [[V]] to [[ADDR]] : $*Int32
   array[0] = make_int()
 
-// CHECK:   [[FN:%.*]] = function_ref @_T010addressors14take_int_inoutys5Int32VzF
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
 // CHECK:   [[T0:%.*]] = function_ref @_T010addressors1DVs5Int32VAEciau
 // CHECK:   [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
 // CHECK:   [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
 // CHECK:   [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK:   [[FN:%.*]] = function_ref @_T010addressors14take_int_inoutys5Int32VzF
 // CHECK:   apply [[FN]]([[ADDR]])
   take_int_inout(&array[1])
 
diff --git a/test/SILGen/assignment.swift b/test/SILGen/assignment.swift
index 6418ee4..722c1bf 100644
--- a/test/SILGen/assignment.swift
+++ b/test/SILGen/assignment.swift
@@ -18,15 +18,14 @@
 // Verify that the LHS is formally evaluated before the RHS.
 // CHECK-LABEL: sil hidden @_T010assignment5test1yyF : $@convention(thin) () -> () {
 func test1() {
-  // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1DC{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[T0:%.*]] = metatype $@thick D.Type
+  // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1DC{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[D:%.*]] = apply [[CTOR]]([[T0]])
   // CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
-  // CHECK: [[SETTER:%.*]] = class_method [[BORROWED_D]] : $D,  #D.child!setter.1
-  // CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
-  // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1CC{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[T0:%.*]] = metatype $@thick C.Type
+  // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1CC{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[C:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thick C.Type) -> @owned C
+  // CHECK: [[SETTER:%.*]] = class_method [[BORROWED_D]] : $D,  #D.child!setter.1
   // CHECK: apply [[SETTER]]([[C]], [[BORROWED_D]])
   // CHECK: end_borrow [[BORROWED_D]] from [[D]]
   // CHECK: destroy_value [[D]]
diff --git a/test/SILGen/auto_closures.swift b/test/SILGen/auto_closures.swift
index ddccafe..91e780a 100644
--- a/test/SILGen/auto_closures.swift
+++ b/test/SILGen/auto_closures.swift
@@ -42,11 +42,11 @@
 public class Sub : Base {
   // CHECK-LABEL: sil hidden @_T013auto_closures3SubC1xAA4BoolVvg : $@convention(method) (@guaranteed Sub) -> Bool {
   // CHECK: bb0([[SELF:%.*]] : $Sub):
-  // CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @_T013auto_closures05call_A8_closureAA4BoolVADyXKF : $@convention(thin)
   // CHECK: [[AUTOCLOSURE_FUNC:%.*]] = function_ref @_T013auto_closures3SubC1xAA4BoolVvgAFyXKfu_ : $@convention(thin) (@owned Sub) -> Bool
   // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK: [[AUTOCLOSURE:%.*]] = partial_apply [[AUTOCLOSURE_FUNC]]([[SELF_COPY]])
   // CHECK: [[CVT:%.*]] = convert_function [[AUTOCLOSURE]]
+  // CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @_T013auto_closures05call_A8_closureAA4BoolVADyXKF : $@convention(thin)
   // CHECK: [[RET:%.*]] = apply [[AUTOCLOSURE_CONSUMER]]([[CVT]])
   // CHECK: return [[RET]] : $Bool
   // CHECK: }
diff --git a/test/SILGen/borrow.swift b/test/SILGen/borrow.swift
index ee208cc..9d6aa8c 100644
--- a/test/SILGen/borrow.swift
+++ b/test/SILGen/borrow.swift
@@ -16,7 +16,6 @@
 // CHECK: bb0:
 // CHECK:   [[BOX:%.*]] = alloc_box ${ var C }, var, name "c"
 // CHECK:   [[PB_BOX:%.*]] = project_box [[BOX]]
-// CHECK:   [[FUNC:%.*]] = function_ref @_T06borrow4useD{{.*}} : $@convention(thin) (@owned D) -> ()
 // CHECK:   [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB_BOX]] : $*C
 // CHECK:   [[CLASS:%.*]] = load [copy] [[ACCESS]]
 // CHECK:   [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
@@ -24,6 +23,7 @@
 // CHECK:   [[ACCESS:%.*]] = begin_access [read] [dynamic] [[OFFSET]] : $*D
 // CHECK:   [[LOADED_VALUE:%.*]] = load [copy] [[ACCESS]]
 // CHECK:   end_borrow [[BORROWED_CLASS]] from [[CLASS]]
+// CHECK:   [[FUNC:%.*]] = function_ref @_T06borrow4useD{{.*}} : $@convention(thin) (@owned D) -> ()
 // CHECK:   apply [[FUNC]]([[LOADED_VALUE]])
 // CHECK:   destroy_value [[CLASS]]
 // CHECK:   destroy_value [[BOX]]
diff --git a/test/SILGen/cf_members.swift b/test/SILGen/cf_members.swift
index fbbacd8..0f93faa 100644
--- a/test/SILGen/cf_members.swift
+++ b/test/SILGen/cf_members.swift
@@ -32,14 +32,14 @@
   var z = Struct1(value: x)
   // The metatype expression should still be evaluated even if it isn't
   // used.
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1CreateSimple
   // CHECK: [[MAKE_METATYPE:%.*]] = function_ref @_T010cf_members12makeMetatype{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[MAKE_METATYPE]]()
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1CreateSimple
   // CHECK: apply [[FN]]([[X]])
   z = makeMetatype().init(value: x)
 
-  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1VABSd5value_tcfCTcTO
   // CHECK: [[SELF_META:%.*]] = metatype $@thin Struct1.Type
+  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1VABSd5value_tcfCTcTO
   // CHECK: [[A:%.*]] = apply [[THUNK]]([[SELF_META]])
   // CHECK: [[BORROWED_A:%.*]] = begin_borrow [[A]]
   // CHECK: [[A_COPY:%.*]] = copy_value [[BORROWED_A]]
@@ -52,21 +52,21 @@
   // let b: @convention(c) (Double) -> Struct1 = Struct1.init(value:)
   // z = b(x)
 
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1InvertInPlace
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[Z]] : $*Struct1
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1InvertInPlace
   // CHECK: apply [[FN]]([[WRITE]])
   z.invert()
 
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Rotate : $@convention(c) (@in Struct1, Double) -> Struct1
   // CHECK: [[WRITE:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[WRITE]]
   // CHECK: store [[ZVAL]] to [trivial] [[ZTMP:%.*]] :
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Rotate : $@convention(c) (@in Struct1, Double) -> Struct1
   // CHECK: apply [[FN]]([[ZTMP]], [[X]])
   z = z.translate(radians: x)
 
-  // CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME:@_T0SC7Struct1V9translateABSd7radians_tFTcTO]]
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME:@_T0SC7Struct1V9translateABSd7radians_tFTcTO]]
   // CHECK: [[C:%.*]] = apply [[THUNK]]([[ZVAL]])
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[C_COPY:%.*]] = copy_value [[BORROWED_C]]
@@ -75,8 +75,13 @@
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   z = c(x)
   // CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME]]
-  // CHECK: thin_to_thick_function [[THUNK]]
+  // CHECK: [[THICK:%.*]] = thin_to_thick_function [[THUNK]]
+  // CHECK: [[BORROW:%.*]] = begin_borrow [[THICK]]
+  // CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
   let d: (Struct1) -> (Double) -> Struct1 = Struct1.translate(radians:)
+  // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+  // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: apply [[COPY]]([[ZVAL]])
   z = d(z)(x)
 
   // TODO: If we implement SE-0042, this should thunk the value Struct1 param
@@ -86,15 +91,15 @@
   //  = Struct1.translate(radians:)
   // z = e(z, x)
 
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Scale
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Scale
   // CHECK: apply [[FN]]([[ZVAL]], [[X]])
   z = z.scale(x)
 
-  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V5scaleABSdFTcTO
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V5scaleABSdFTcTO
   // CHECK: [[F:%.*]] = apply [[THUNK]]([[ZVAL]])
   // CHECK: [[BORROWED_F:%.*]] = begin_borrow [[F]]
   // CHECK: [[F_COPY:%.*]] = copy_value [[BORROWED_F]]
@@ -118,8 +123,8 @@
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
   // CHECK: store [[ZVAL]] to [trivial] [[ZTMP:%.*]] :
   // CHECK: [[ZVAL_2:%.*]] = load [trivial] [[ZTMP]]
-  // CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetRadius : $@convention(c) (@in Struct1) -> Double
   // CHECK: store [[ZVAL_2]] to [trivial] [[ZTMP_2:%.*]] :
+  // CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetRadius : $@convention(c) (@in Struct1) -> Double
   // CHECK: apply [[GET]]([[ZTMP_2]])
   _ = z.radius
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
@@ -133,8 +138,8 @@
   // CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetAltitude : $@convention(c) (Struct1) -> Double
   // CHECK: apply [[GET]]([[ZVAL]])
   _ = z.altitude
-  // CHECK: [[SET:%.*]] = function_ref @IAMStruct1SetAltitude : $@convention(c) (@inout Struct1, Double) -> ()
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[Z]] : $*Struct1
+  // CHECK: [[SET:%.*]] = function_ref @IAMStruct1SetAltitude : $@convention(c) (@inout Struct1, Double) -> ()
   // CHECK: apply [[SET]]([[WRITE]], [[X]])
   z.altitude = x
   
@@ -147,8 +152,8 @@
   // CHECK: [[FN:%.*]] = function_ref @IAMStruct1StaticMethod
   // CHECK: apply [[FN]]()
   var y = Struct1.staticMethod()
-  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V12staticMethods5Int32VyFZTcTO
   // CHECK: [[SELF:%.*]] = metatype
+  // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V12staticMethods5Int32VyFZTcTO
   // CHECK: [[I:%.*]] = apply [[THUNK]]([[SELF]])
   // CHECK: [[BORROWED_I:%.*]] = begin_borrow [[I]]
   // CHECK: [[I_COPY:%.*]] = copy_value [[BORROWED_I]]
@@ -187,23 +192,27 @@
   // CHECK: apply [[GET]]()
   _ = makeMetatype().getOnlyProperty
 
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesLast : $@convention(c) (Double, Struct1) -> ()
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesLast : $@convention(c) (Double, Struct1) -> ()
   // CHECK: apply [[FN]]([[X]], [[ZVAL]])
   z.selfComesLast(x: x)
+  // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+  // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
   let k: (Double) -> () = z.selfComesLast(x:)
   k(x)
   let l: (Struct1) -> (Double) -> () = Struct1.selfComesLast(x:)
+  // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+  // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
   l(z)(x)
 
   // TODO: If we implement SE-0042, this should thunk to reorder the arguments.
   // let m: @convention(c) (Struct1, Double) -> () = Struct1.selfComesLast(x:)
   // m(z, x)
 
-  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesThird : $@convention(c) (Int32, Float, Struct1, Double) -> ()
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
   // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+  // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesThird : $@convention(c) (Int32, Float, Struct1, Double) -> ()
   // CHECK: apply [[FN]]({{.*}}, {{.*}}, [[ZVAL]], [[X]])
   z.selfComesThird(a: y, b: 0, x: x)
   let n: (Int32, Float, Double) -> () = z.selfComesThird(a:b:x:)
diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift
index e2feaab..7048696 100644
--- a/test/SILGen/class_bound_protocols.swift
+++ b/test/SILGen/class_bound_protocols.swift
@@ -193,7 +193,6 @@
   // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
   // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
   // CHECK-NEXT: [[X_PAYLOAD_RELOADED:%.*]] = load [take] [[TEMPORARY]]
-  // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutatingCounter!getter.1 : <Self where Self : HasMutatingMethod> (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
   //
   // ** *NOTE* This extra copy is here since RValue invariants enforce that all
   // ** loadable objects are actually loaded. So we form the RValue and
@@ -203,6 +202,7 @@
   // CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
   // CHECK-NEXT: store [[X_PAYLOAD_RELOADED:%.*]] to [init] [[TEMPORARY_2]]
   // 
+  // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutatingCounter!getter.1 : <Self where Self : HasMutatingMethod> (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
   // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}") InheritsMutatingMethod>([[TEMPORARY_2]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
   // CHECK-NEXT: [[X_VALUE:%.*]] = load [take] [[TEMPORARY_2]] : $*@opened("{{.*}}") InheritsMutatingMethod
   // CHECK-NEXT: destroy_value [[X_VALUE]] : $@opened("{{.*}}") InheritsMutatingMethod
diff --git a/test/SILGen/class_resilience.swift b/test/SILGen/class_resilience.swift
index c9442fe..5db4d2d 100644
--- a/test/SILGen/class_resilience.swift
+++ b/test/SILGen/class_resilience.swift
@@ -17,6 +17,26 @@
 
 public class MyResilientClass {
   public final var finalProperty: String = "MyResilientClass.finalProperty"
+
+  // CHECK-LABEL: sil [thunk] @_T016class_resilience16MyResilientClassC17publicMethodFirstSiSgyFTj : $@convention(method) (@guaranteed MyResilientClass) -> Optional<Int>
+  // CHECK:   class_method %0 : $MyResilientClass, #MyResilientClass.publicMethodFirst!1 : (MyResilientClass) -> () -> Int?, $@convention(method) (@guaranteed MyResilientClass) -> Optional<Int>
+  // CHECK:   return
+  public func publicMethodFirst() -> Int? { return nil }
+
+  // CHECK-LABEL: sil [thunk] @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+  // CHECK:   class_method %1 : $MyResilientClass, #MyResilientClass.publicMethodSecond!1 : (MyResilientClass) -> (AnyObject) -> (), $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+  // CHECK:   return
+  public func publicMethodSecond(_ a: AnyObject) {}
+}
+
+public class MyResilientSubclass : MyResilientClass {
+  // This override changes ABI so it gets its own dispatch thunk
+  // CHECK-LABEL: sil [thunk] @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj : $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+  // CHECK:   class_method %0 : $MyResilientSubclass, #MyResilientSubclass.publicMethodFirst!1 : (MyResilientSubclass) -> () -> Int, $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+  // CHECK: return
+  public override func publicMethodFirst() -> Int { return 0 }
+
+  public override func publicMethodSecond(_ a: AnyObject?) {}
 }
 
 // Accessing final property of resilient class from my resilience domain
@@ -38,6 +58,39 @@
   func newMethod() {}
 }
 
+// CHECK-LABEL: sil @_T016class_resilience19callResilientMethodyAA02MyD8SubclassCF : $@convention(thin) (@owned MyResilientSubclass) -> ()
+public func callResilientMethod(_ s: MyResilientSubclass) {
+// CHECK:   class_method {{.*}} : $MyResilientSubclass, #MyResilientSubclass.publicMethodFirst!1
+  _ = s.publicMethodFirst()
+// CHECK:   class_method {{.*}} : $MyResilientSubclass, #MyResilientSubclass.publicMethodSecond!1
+  s.publicMethodSecond(nil)
+// CHECK:   return
+}
+
+// CHECK-LABEL: sil [serialized] @_T016class_resilience29callResilientMethodInlineableyAA02MyD8SubclassCF : $@convention(thin) (@owned MyResilientSubclass) -> ()
+@_inlineable public func callResilientMethodInlineable(_ s: MyResilientSubclass) {
+// CHECK:   [[FN:%.*]] = function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj : $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+  _ = s.publicMethodFirst()
+  // CHECK:   [[FN:%.*]] = function_ref @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+  // CHECK:   [[CONVERTED:%.*]] = convert_function [[FN]] : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> () to $@convention(method) (@owned Optional<AnyObject>, @guaranteed MyResilientSubclass) -> ()
+  s.publicMethodSecond(nil)
+
+  // CHECK:   function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTc
+  _ = s.publicMethodFirst
+
+  // CHECK:   function_ref @_T016class_resilience19MyResilientSubclassC18publicMethodSecondyyXlSgFTc
+  _ = s.publicMethodSecond
+// CHECK:   return
+}
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTc : $@convention(thin) (@owned MyResilientSubclass) -> @owned @callee_owned () -> Int
+// CHECK:     function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj
+// CHECK:     return
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @_T016class_resilience19MyResilientSubclassC18publicMethodSecondyyXlSgFTc : $@convention(thin) (@owned MyResilientSubclass) -> @owned @callee_owned (@owned Optional<AnyObject>) -> ()
+// CHECK:     function_ref @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+// CHECK:     return
+
 // Note: no entries for [inherited] methods
 
 // CHECK-LABEL: sil_vtable SubclassOfOutsideChild {
diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift
index 3ed9217..6c28e80 100644
--- a/test/SILGen/closures.swift
+++ b/test/SILGen/closures.swift
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen -enable-guaranteed-closure-contexts %s | %FileCheck %s --check-prefix=GUARANTEED
 
 import Swift
 
@@ -394,6 +395,17 @@
 // CHECK:   return [[INT_IN_CLASS]]
 // CHECK: } // end sil function '_T08closures18closeOverLetLValueyyFSiycfU_'
 
+// GUARANTEED-LABEL: sil private @_T08closures18closeOverLetLValueyyFSiycfU_ : $@convention(thin) (@guaranteed ClassWithIntProperty) -> Int {
+// GUARANTEED: bb0(%0 : @guaranteed $ClassWithIntProperty):
+// GUARANTEED:   [[TMP:%.*]] = alloc_stack $ClassWithIntProperty
+// GUARANTEED:   [[COPY:%.*]] = copy_value %0 : $ClassWithIntProperty
+// GUARANTEED:   store [[COPY]] to [init] [[TMP]] : $*ClassWithIntProperty
+// GUARANTEED:   [[LOADED_COPY:%.*]] = load [copy] [[TMP]]
+// GUARANTEED:   [[BORROWED:%.*]] = begin_borrow [[LOADED_COPY]]
+// GUARANTEED:   end_borrow [[BORROWED]] from [[LOADED_COPY]]
+// GUARANTEED:   destroy_value [[LOADED_COPY]]
+// GUARANTEED:   destroy_addr [[TMP]]
+// GUARANTEED: } // end sil function '_T08closures18closeOverLetLValueyyFSiycfU_'
 
 
 // Use an external function so inout deshadowing cannot see its body.
@@ -442,8 +454,8 @@
     // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
     // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
     // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-    // CHECK:   [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
     // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+    // CHECK:   [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
     // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
     // CHECK:   destroy_value [[ARG_COPY_SUPER]]
     // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -480,8 +492,8 @@
       // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
       // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
       // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase)
       // CHECK:   destroy_value [[ARG_COPY_SUPER]]
       // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -517,8 +529,8 @@
     // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
     // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
     // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-    // CHECK:   [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
     // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+    // CHECK:   [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
     // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
     // CHECK:   destroy_value [[ARG_COPY_SUPER]]
     // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -556,8 +568,8 @@
       // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
       // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
       // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
       // CHECK:   destroy_value [[ARG_COPY_SUPER]]
       // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -596,8 +608,8 @@
       // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
       // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
       // CHECK:   [[ARG_COPY_SUPERCAST:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   [[BORROWED_ARG_COPY_SUPERCAST:%.*]] = begin_borrow [[ARG_COPY_SUPERCAST]]
+      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPERCAST]])
       // CHECK:   destroy_value [[ARG_COPY_SUPERCAST]]
       // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -622,13 +634,13 @@
   func f() {
     // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@owned SuperSub) -> () {
     // CHECK: bb0([[ARG:%.*]] : @owned $SuperSub):
-    // CHECK:   [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
     // CHECK:   [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:_T08closures8SuperSubC1fyyFyycfU_yyKXKfu_]] : $@convention(thin) (@owned SuperSub) -> @error Error
     // CHECK:   [[ARG_COPY:%.*]] = copy_value [[ARG]]
     // CHECK:   [[PA:%.*]] = partial_apply [[INNER]]([[ARG_COPY]])
     // CHECK:   [[CVT:%.*]] = convert_function [[PA]]
     // CHECK:   [[REABSTRACT_PA:%.*]] = partial_apply {{.*}}([[CVT]])
     // CHECK:   [[REABSTRACT_CVT:%.*]] = convert_function [[REABSTRACT_PA]]    
+    // CHECK:   [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
     // CHECK:   try_apply [[TRY_APPLY_AUTOCLOSURE]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
     // CHECK: [[NORMAL_BB]]{{.*}}
     // CHECK:   destroy_value [[ARG]]
@@ -639,8 +651,8 @@
       // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
       // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
       // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   destroy_value [[ARG_COPY_SUPER]]
       // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -659,13 +671,13 @@
   func g() {
     // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@owned SuperSub) -> ()
     // CHECK: bb0([[ARG:%.*]] : @owned $SuperSub):
-    // CHECK:   [[TRY_APPLY_FUNC:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
     // CHECK:   [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:_T08closures8SuperSubC1g.*]] : $@convention(thin) (@owned SuperSub) -> @error Error
     // CHECK:   [[ARG_COPY:%.*]] = copy_value [[ARG]]
     // CHECK:   [[PA:%.*]] = partial_apply [[INNER]]([[ARG_COPY]])
     // CHECK:   [[CVT:%.*]] = convert_function [[PA]] : $@callee_owned () -> @error Error to $@noescape @callee_owned () -> @error Error
     // CHECK:   [[REABSTRACT_PA:%.*]] = partial_apply {{%.*}}([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> @error Error) -> (@out (), @error Error)
     // CHECK:   [[REABSTRACT_CVT:%.*]] = convert_function [[REABSTRACT_PA]]
+    // CHECK:   [[TRY_APPLY_FUNC:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
     // CHECK:   try_apply [[TRY_APPLY_FUNC]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
     // CHECK: [[NORMAL_BB]]{{.*}}
     // CHECK:   destroy_value [[ARG]]
@@ -676,8 +688,8 @@
       // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
       // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
       // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
-      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+      // CHECK:   [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
       // CHECK:   = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
       // CHECK:   destroy_value [[ARG_COPY_SUPER]]
       // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -767,8 +779,8 @@
 // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
 // CHECK:   [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $GenericDerived<Ocean> to $ConcreteBase
-// CHECK:   [[METHOD:%.*]] = function_ref @_T08closures12ConcreteBaseC4swimyyF
 // CHECK:   [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+// CHECK:   [[METHOD:%.*]] = function_ref @_T08closures12ConcreteBaseC4swimyyF
 // CHECK:   apply [[METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
 // CHECK:   destroy_value [[ARG_COPY_SUPER]]
 // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
diff --git a/test/SILGen/closures_callee_guaranteed.swift b/test/SILGen/closures_callee_guaranteed.swift
index a71221e..bc716f9 100644
--- a/test/SILGen/closures_callee_guaranteed.swift
+++ b/test/SILGen/closures_callee_guaranteed.swift
@@ -21,10 +21,10 @@
 }
 
 // CHECK-LABEL: sil @{{.*}}test{{.*}} : $@convention(thin) () -> ()
-// CHECK:   [[A:%.*]] = function_ref @{{.*}}apply{{.*}} : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
 // CHECK:   [[C1:%.*]] = function_ref @{{.*}}test{{.*}} : $@convention(thin) () -> Int
 // CHECK:   [[C2:%.*]] = convert_function [[C1]] : $@convention(thin) () -> Int to $@convention(thin) @noescape () -> Int
 // CHECK:   [[C3:%.*]] = thin_to_thick_function [[C2]] : $@convention(thin) @noescape () -> Int to $@noescape @callee_guaranteed () -> Int
+// CHECK:   [[A:%.*]] = function_ref @{{.*}}apply{{.*}} : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
 // CHECK:   apply [[A]]([[C3]]) : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
 public func test() {
   let res = apply({ return 1 })
diff --git a/test/SILGen/complete_object_init.swift b/test/SILGen/complete_object_init.swift
index 8363f9c..0c826ac 100644
--- a/test/SILGen/complete_object_init.swift
+++ b/test/SILGen/complete_object_init.swift
@@ -17,11 +17,10 @@
 // CHECK:   [[PB:%.*]] = project_box [[UNINIT_SELF]]
 // CHECK:   store [[SELF_PARAM]] to [init] [[PB]] : $*A
 // CHECK:   [[SELFP:%[0-9]+]] = load [take] [[PB]] : $*A
-// CHECK:   [[BORROWED_SELFP:%.*]] = begin_borrow [[SELFP]]
-// CHECK:   [[INIT:%[0-9]+]] = class_method [[BORROWED_SELFP]] : $A, #A.init!initializer.1 : (A.Type) -> (X) -> A, $@convention(method) (X, @owned A) -> @owned A
-// CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T020complete_object_init1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
 // CHECK:   [[X_META:%[0-9]+]] = metatype $@thin X.Type
+// CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T020complete_object_init1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
 // CHECK:   [[X:%[0-9]+]] = apply [[X_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+// CHECK:   [[INIT:%[0-9]+]] = class_method [[SELFP]] : $A, #A.init!initializer.1 : (A.Type) -> (X) -> A, $@convention(method) (X, @owned A) -> @owned A
 // CHECK:   [[INIT_RESULT:%[0-9]+]] = apply [[INIT]]([[X]], [[SELFP]]) : $@convention(method) (X, @owned A) -> @owned A
 // CHECK:   store [[INIT_RESULT]] to [init] [[PB]] : $*A
 // CHECK:   [[RESULT:%[0-9]+]] = load [copy] [[PB]] : $*A
diff --git a/test/SILGen/conditional_conformance.swift b/test/SILGen/conditional_conformance.swift
new file mode 100644
index 0000000..a43dc60
--- /dev/null
+++ b/test/SILGen/conditional_conformance.swift
@@ -0,0 +1,80 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol P1 {
+  func normal()
+  func generic<T: P3>(_: T)
+}
+protocol P2 {}
+protocol P3 {}
+
+protocol P4 {
+  associatedtype AT
+}
+
+struct Conformance<A> {}
+extension Conformance: P1 where A: P2 {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P2> Conformance<A>: P1 module conditional_conformance {
+// CHECK-NEXT:    method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance11ConformanceVyxGAA2P1A2A2P2RzlAaEP6normalyyFTW	// protocol witness for P1.normal() in conformance <A> Conformance<A>
+// CHECK-NEXT:    method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance11ConformanceVyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW	// protocol witness for P1.generic<A>(_:) in conformance <A> Conformance<A>
+// CHECK-NEXT:    conditional_conformance (τ_0_0: P2): dependent
+// CHECK-NEXT:  }
+
+struct ConformanceAssoc<A> {}
+extension ConformanceAssoc: P1 where A: P4, A.AT: P2 {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P4, A.AT : P2> ConformanceAssoc<A>: P1 module conditional_conformance {
+// CHECK-NEXT:    method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance16ConformanceAssocVyxGAA2P1A2A2P4RzAA2P22ATRpzlAaEP6normalyyFTW // protocol witness for P1.normal() in conformance <A> ConformanceAssoc<A>
+// CHECK-NEXT:    method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance16ConformanceAssocVyxGAA2P1A2A2P4RzAA2P22ATRpzlAaEP7genericyqd__AA2P3Rd__lFTW // protocol witness for P1.generic<A>(_:) in conformance <A> ConformanceAssoc<A>
+// CHECK-NEXT:    conditional_conformance (τ_0_0: P4): dependent
+// CHECK-NEXT:    conditional_conformance (τ_0_0.AT: P2): dependent
+// CHECK-NEXT:  }
+
+/*
+FIXME: same type constraints are modelled incorrectly.
+struct SameTypeConcrete<B> {}
+extension SameTypeConcrete: P1 where B == Int {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+
+struct SameTypeGeneric<C, D> {}
+extension SameTypeGeneric: P1 where C == D {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+
+struct SameTypeGenericConcrete<E, F> {}
+extension SameTypeGenericConcrete: P1 where E == [F] {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+
+struct Everything<G, H, I, J, K, L> {}
+extension Everything: P1 where G: P2, H == Int, I == J, K == [L] {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+*/
+
+struct IsP2: P2 {}
+struct IsNotP2 {}
+
+class Base<A> {}
+extension Base: P1 where A: P2 {
+  func normal() {}
+  func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P2> Base<A>: P1 module conditional_conformance {
+// CHECK-NEXT:  method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance4BaseCyxGAA2P1A2A2P2RzlAaEP6normalyyFTW	// protocol witness for P1.normal() in conformance <A> Base<A>
+// CHECK-NEXT:    method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance4BaseCyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW	// protocol witness for P1.generic<A>(_:) in conformance <A> Base<A>
+// CHECK-NEXT:    conditional_conformance (τ_0_0: P2): dependent
+// CHECK-NEXT:  }
+
+// These don't get separate witness tables, but shouldn't crash anything.
+class SubclassGood: Base<IsP2> {}
+class SubclassBad: Base<IsNotP2> {}
diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift
index d526ac7..e0f2fac 100644
--- a/test/SILGen/default_arguments.swift
+++ b/test/SILGen/default_arguments.swift
@@ -10,9 +10,9 @@
 
 // Default argument for first parameter.
 // CHECK-LABEL: sil hidden @_T017default_arguments7defarg1ySi1i_Sd1dSS1stFfA_ : $@convention(thin) () -> Int
-// CHECK: [[CVT:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[INT:%[0-9]+]] = metatype $@thin Int.Type
 // CHECK: [[LIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 17
+// CHECK: [[CVT:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
 // CHECK: [[RESULT:%[0-9]+]] = apply [[CVT]]([[LIT]], [[INT]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
 // CHECK: return [[RESULT]] : $Int
 
@@ -28,15 +28,15 @@
 
 // CHECK-LABEL: sil hidden @_T017default_arguments15testDefaultArg1yyF
 func testDefaultArg1() {
-  // CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{[_0-9a-zA-Z]*}}F
-  // CHECK: [[LITFN:%[0-9]+]] = function_ref @_T0S2d{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[FLOAT64:%[0-9]+]] = metatype $@thin Double.Type
   // CHECK: [[FLOATLIT:%[0-9]+]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x4009000000000000|0x4000C800000000000000}}
+  // CHECK: [[LITFN:%[0-9]+]] = function_ref @_T0S2d{{[_0-9a-zA-Z]*}}fC
   // CHECK: [[FLOATVAL:%[0-9]+]] = apply [[LITFN]]([[FLOATLIT]], [[FLOAT64]])
   // CHECK: [[DEF0FN:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{.*}}A_
   // CHECK: [[DEF0:%[0-9]+]] = apply [[DEF0FN]]()
   // CHECK: [[DEF2FN:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{.*}}A1_
   // CHECK: [[DEF2:%[0-9]+]] = apply [[DEF2FN]]()
+  // CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FNREF]]([[DEF0]], [[FLOATVAL]], [[DEF2]])
   defarg1(d:3.125)
 }
@@ -45,15 +45,15 @@
 
 // CHECK-LABEL: sil hidden @_T017default_arguments15testDefaultArg2{{[_0-9a-zA-Z]*}}F
 func testDefaultArg2() {
-// CHECK:  [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Double, @owned String) -> ()
-// CHECK:  [[LITFN:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
 // CHECK:  [[INT64:%[0-9]+]] = metatype $@thin Int.Type
 // CHECK:  [[INTLIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+// CHECK:  [[LITFN:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
 // CHECK:  [[I:%[0-9]+]] = apply [[LITFN]]([[INTLIT]], [[INT64]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
 // CHECK:  [[DFN:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{.*}}A0_ : $@convention(thin) () -> Double
 // CHECK:  [[D:%[0-9]+]] = apply [[DFN]]() : $@convention(thin) () -> Double
 // CHECK:  [[SFN:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{.*}}A1_ : $@convention(thin) () -> @owned String
 // CHECK:  [[S:%[0-9]+]] = apply [[SFN]]() : $@convention(thin) () -> @owned String
+// CHECK:  [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Double, @owned String) -> ()
 // CHECK:  apply [[FNREF]]([[I]], [[D]], [[S]]) : $@convention(thin) (Int, Double, @owned String) -> ()
   defarg2(5)
 }
@@ -178,8 +178,8 @@
 
 // CHECK: sil hidden @_T017default_arguments13testSubDefArgAA0deF0CyF : $@convention(thin) () -> @owned SubDefArg
 func testSubDefArg() -> SubDefArg {
-  // CHECK: function_ref @_T017default_arguments9SubDefArgC{{[_0-9a-zA-Z]*}}fC
   // CHECK: function_ref @_T017default_arguments11SuperDefArgCACSi3int_tcfcfA_
+  // CHECK: function_ref @_T017default_arguments9SubDefArgC{{[_0-9a-zA-Z]*}}fC
   // CHECK: return
   return SubDefArg()
 }
@@ -219,20 +219,18 @@
 
 // CHECK-LABEL: sil hidden @_T017default_arguments32testDefaultArgumentReabstractionyyF
 // function_ref default_arguments.ReabstractDefaultArgument.__allocating_init <A>(default_arguments.ReabstractDefaultArgument<A>.Type)(a : (A, A) -> Swift.Bool) -> default_arguments.ReabstractDefaultArgument<A>
-// CHECK: [[INITFN:%[0-9]+]] = function_ref @_T017default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
-// %1 = metatype $@thick ReabstractDefaultArgument<Int>.Type
-// function_ref default_arguments.ReabstractDefaultArgument.(init <A>(default_arguments.ReabstractDefaultArgument<A>.Type) -> (a : (A, A) -> Swift.Bool) -> default_arguments.ReabstractDefaultArgument<A>).(default argument 0)
-// CHECK: %2 = function_ref @_T017default_arguments25ReabstractDefaultArgument{{.*}} : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
-// CHECK-NEXT: %3 = apply %2<Int>() : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
+// CHECK: [[FN:%.*]] = function_ref @_T017default_arguments25ReabstractDefaultArgument{{.*}} : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Int>() : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
 // CHECK-NEXT: function_ref reabstraction thunk helper from @callee_owned (@in Swift.Int, @in Swift.Int) -> (@unowned Swift.Bool) to @callee_owned (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool)
-// CHECK-NEXT: %4 = function_ref @_T0S2iSbIxiid_S2iSbIxyyd_TR : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
-// CHECK-NEXT: %5 = partial_apply %4(%3) : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
-// CHECK-NEXT: %6 = convert_function %5
+// CHECK-NEXT: [[THUNK:%.*]] = function_ref @_T0S2iSbIxiid_S2iSbIxyyd_TR : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [[THUNK]]([[RESULT]]) : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_function [[FN]]
 // function_ref reabstraction thunk helper from @callee_owned (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.Int, @in Swift.Int) -> (@unowned Swift.Bool)
-// CHECK: %7 = function_ref @_T0S2iSbIxyyd_S2iSbIxiid_TR : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
-// CHECK-NEXT: %8 = partial_apply %7(%6) : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
-// CHECK-NEXT: %9 = convert_function %8
-// CHECK-NEXT: apply [[INITFN]]<Int>(%9, 
+// CHECK: [[THUNK:%.*]] = function_ref @_T0S2iSbIxyyd_S2iSbIxiid_TR : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [[THUNK]]([[CONV_FN]]) : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_function [[FN]]
+// CHECK: [[INITFN:%[0-9]+]] = function_ref @_T017default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
+// CHECK-NEXT: apply [[INITFN]]<Int>([[CONV_FN]], 
 
 func testDefaultArgumentReabstraction() {
   _ = ReabstractDefaultArgument<Int>()
@@ -256,9 +254,9 @@
 // CHECK: integer_literal $Builtin.Int2048, 97
 
 // CHECK-LABEL: sil hidden @_T017default_arguments14test_r18400194yyF
-// CHECK: function_ref @_T017default_arguments9r18400194ySi_Si1xtF : $@convention(thin) (Int, Int) -> (){{.*}} // user: %7
 // CHECK: integer_literal $Builtin.Int2048, 1
 // CHECK:  function_ref @_T017default_arguments9r18400194ySi_Si1xtFfA0_ : $@convention(thin) () -> Int
+// CHECK: function_ref @_T017default_arguments9r18400194ySi_Si1xtF : $@convention(thin) (Int, Int) -> (){{.*}}
 func test_r18400194() {
   (r18400194)(1)
 }
diff --git a/test/SILGen/default_arguments_generic.swift b/test/SILGen/default_arguments_generic.swift
index 93ed6c0..a825808 100644
--- a/test/SILGen/default_arguments_generic.swift
+++ b/test/SILGen/default_arguments_generic.swift
@@ -42,8 +42,8 @@
 func testInitializable() {
   // The ".init" is required to trigger the crash that used to happen.
   _ = Generic<InitializableImpl>.init()
-  // CHECK: [[INIT:%.+]] = function_ref @_T025default_arguments_generic7GenericVACyxGxcfC
   // CHECK: function_ref @_T025default_arguments_generic7GenericVACyxGxcfcfA_ : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> @out τ_0_0
+  // CHECK: [[INIT:%.+]] = function_ref @_T025default_arguments_generic7GenericVACyxGxcfC
   // CHECK: apply [[INIT]]<InitializableImpl>({{%.+}}, {{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @thin Generic<τ_0_0>.Type) -> Generic<τ_0_0>
 } // CHECK: end sil function '_T025default_arguments_generic17testInitializableyyF'
 
diff --git a/test/SILGen/default_arguments_imported.swift b/test/SILGen/default_arguments_imported.swift
index f951038..95ad609 100644
--- a/test/SILGen/default_arguments_imported.swift
+++ b/test/SILGen/default_arguments_imported.swift
@@ -8,23 +8,23 @@
 
 // CHECK-LABEL: sil hidden @_T026default_arguments_imported9testGizmo{{[_0-9a-zA-Z]*}}F
 func testGizmo(gizmo: Gizmo) {
-  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.enumerateSubGizmos!1.foreign
   // CHECK: function_ref @_T0SqxSgyt10nilLiteral_tcfC
+  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.enumerateSubGizmos!1.foreign
   gizmo.enumerateSubGizmos()
 } // CHECK: } // end sil function '_T026default_arguments_imported9testGizmoySo0E0C5gizmo_tF'
 
 // CHECK-LABEL: sil hidden @_T026default_arguments_imported21testNonnullDictionaryySo5GizmoC5gizmo_tF
 func testNonnullDictionary(gizmo: Gizmo) {
-  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheThing!1.foreign
   // CHECK-NOT: nilLiteral
   // CHECK: function_ref @_T0s10DictionaryVAByxq_Gx_q_t17dictionaryLiterald_tcfC
+  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheThing!1.foreign
   gizmo.doTheThing()
 } // CHECK: } // end sil function '_T026default_arguments_imported21testNonnullDictionaryySo5GizmoC5gizmo_tF'
 
 // CHECK-LABEL: sil hidden @_T026default_arguments_imported22testNullableDictionaryySo5GizmoC5gizmo_tF
 func testNullableDictionary(gizmo: Gizmo) {
-  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheOtherThing!1.foreign
   // CHECK-NOT: dictionaryLiteral
   // CHECK: function_ref @_T0SqxSgyt10nilLiteral_tcfC
+  // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheOtherThing!1.foreign
   gizmo.doTheOtherThing()
 } // CHECK: } // end sil function '_T026default_arguments_imported22testNullableDictionaryySo5GizmoC5gizmo_tF'
diff --git a/test/SILGen/default_arguments_serialized.swift b/test/SILGen/default_arguments_serialized.swift
index 3391474..d264736 100644
--- a/test/SILGen/default_arguments_serialized.swift
+++ b/test/SILGen/default_arguments_serialized.swift
@@ -23,9 +23,9 @@
 public func hasDefaultArguments(x: Int = 0, y: String = defaultString()) {}
 
 // CHECK-LABEL: sil @_T028default_arguments_serialized21callsDefaultArgumentsyyF : $@convention(thin) () -> ()
-// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytF : $@convention(thin) (Int, @owned String) -> ()
 // CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytFfA_ : $@convention(thin) () -> Int
 // CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytFfA0_ : $@convention(thin) () -> @owned String
+// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytF : $@convention(thin) (Int, @owned String) -> ()
 // CHECK: apply
 // CHECK: return
 public func callsDefaultArguments() {
@@ -37,8 +37,8 @@
 // even if *this* module is built in Swift 3 mode.
 
 // CHECK-LABEL: sil @_T028default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
-// CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
 // CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
+// CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
 // CHECK: apply
 // CHECK: return
 
@@ -46,15 +46,16 @@
 // other module.
 
 // OPT-LABEL: sil @_T028default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
-// OPT: [[FN:%.*]] = function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> () // user: %3
 // OPT: [[INT_VAL:%.*]] = integer_literal [[INT_TYPE:\$Builtin.Int(32|64)]], 0
 // OPT: [[INT:%.*]] = struct $Int ([[INT_VAL]] : [[INT_TYPE]]
+// OPT: [[FN:%.*]] = function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
 // OPT: apply [[FN]]([[INT]]) : $@convention(thin) (Int) -> ()
 // OPT: return
 public func callsOtherDefaultArguments() {
   otherDefaultArguments()
 }
 
+// CHECK-LABEL: sil [serialized] @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
+
 // CHECK-LABEL: sil @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
 
-// CHECK-LABEL: sil [serialized] @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
diff --git a/test/SILGen/default_constructor.swift b/test/SILGen/default_constructor.swift
index 7ffa02b..24f77ac 100644
--- a/test/SILGen/default_constructor.swift
+++ b/test/SILGen/default_constructor.swift
@@ -15,13 +15,13 @@
 }
 
 // CHECK-LABEL: sil hidden [transparent] @_T019default_constructor1DV1iSivpfi : $@convention(thin) () -> (Int, Double)
-// CHECK:      [[FN:%.*]] = function_ref @_T0S2iBi2048_22_builtinIntegerLiteral_tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
-// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Int.Type
+// CHECK:      [[METATYPE:%.*]] = metatype $@thin Int.Type
 // CHECK-NEXT: [[VALUE:%.*]] = integer_literal $Builtin.Int2048, 2
+// CHECK:      [[FN:%.*]] = function_ref @_T0S2iBi2048_22_builtinIntegerLiteral_tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
 // CHECK-NEXT: [[LEFT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
-// CHECK:      [[FN:%.*]] = function_ref @_T0S2dBf{{64|80}}_20_builtinFloatLiteral_tcfC : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Double.Type
 // CHECK-NEXT: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x400C000000000000|0x4000E000000000000000}}
+// CHECK:      [[FN:%.*]] = function_ref @_T0S2dBf{{64|80}}_20_builtinFloatLiteral_tcfC : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
 // CHECK-NEXT: [[RIGHT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
 // CHECK-NEXT: [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Double)
 // CHECK-NEXT: return [[RESULT]] : $(Int, Double)
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 9cea33c..27414e3 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -334,13 +334,13 @@
   }
 
   // CHECK-LABEL: sil hidden @_T0So5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
-  // CHECK:         objc_method {{%.*}} : $@thick Gizmo.Type, #Gizmo.init!allocator.1.foreign
+  // CHECK:         objc_method {{%.*}} : $@objc_metatype Gizmo.Type, #Gizmo.init!allocator.1.foreign
   convenience init(foreignClassFactory x: Int) {
     self.init(stuff: x)
   }
 
   // CHECK-LABEL: sil hidden @_T0So5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
-  // CHECK:         objc_method {{%.*}} : $@thick Gizmo.Type, #Gizmo.init!allocator.1.foreign
+  // CHECK:         objc_method {{%.*}} : $@objc_metatype Gizmo.Type, #Gizmo.init!allocator.1.foreign
   convenience init(foreignClassExactFactory x: Int) {
     self.init(exactlyStuff: x)
   }
@@ -424,8 +424,8 @@
   // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.extensionProp!getter.1.foreign
   _ = obj.extensionProp
 
-  // CHECK: objc_method {{%.*}} : $@thick ObjCOtherFile.Type, #ObjCOtherFile.extensionClassProp!getter.1.foreign
-  // CHECK-NEXT: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+  // CHECK: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+  // CHECK-NEXT: objc_method {{%.*}} : $@objc_metatype ObjCOtherFile.Type, #ObjCOtherFile.extensionClassProp!getter.1.foreign
   _ = type(of: obj).extensionClassProp
 
   // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.dynExtensionMethod!1.foreign
@@ -433,8 +433,8 @@
   // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.dynExtensionProp!getter.1.foreign
   _ = obj.dynExtensionProp
 
-  // CHECK: objc_method {{%.*}} : $@thick ObjCOtherFile.Type, #ObjCOtherFile.dynExtensionClassProp!getter.1.foreign
-  // CHECK-NEXT: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+  // CHECK: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+  // CHECK-NEXT: objc_method {{%.*}} : $@objc_metatype ObjCOtherFile.Type, #ObjCOtherFile.dynExtensionClassProp!getter.1.foreign
   _ = type(of: obj).dynExtensionClassProp
 }
 
diff --git a/test/SILGen/dynamic_lookup.swift b/test/SILGen/dynamic_lookup.swift
index 978a27c..92d9786 100644
--- a/test/SILGen/dynamic_lookup.swift
+++ b/test/SILGen/dynamic_lookup.swift
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
+// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module -enable-guaranteed-closure-contexts %s | %FileCheck %s --check-prefix=GUARANTEED
 
 // REQUIRES: objc_interop
 
@@ -27,8 +28,7 @@
   // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK: [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
   // CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
-  // CHECK: [[BORROWED_OPENED_ARG_COPY:%.*]] = begin_borrow [[OPENED_ARG_COPY]]
-  // CHECK: [[METHOD:%[0-9]+]] = objc_method [[BORROWED_OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #X.f!1.foreign : (X) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+  // CHECK: [[METHOD:%[0-9]+]] = objc_method [[OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #X.f!1.foreign : (X) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
   // CHECK: apply [[METHOD]]([[OPENED_ARG_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
   // CHECK: destroy_value [[OPENED_ARG_COPY]]
   // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -43,8 +43,7 @@
   // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK:   [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
   // CHECK:   [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
-  // CHECK:   [[BORROWED_OPENED_ARG_COPY:%.*]] = begin_borrow [[OPENED_ARG_COPY]]
-  // CHECK:   [[METHOD:%[0-9]+]] = objc_method [[BORROWED_OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #P.g!1.foreign : <Self where Self : P> (Self) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+  // CHECK:   [[METHOD:%[0-9]+]] = objc_method [[OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #P.g!1.foreign : <Self where Self : P> (Self) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
   // CHECK:   apply [[METHOD]]([[OPENED_ARG_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
   // CHECK:   destroy_value [[OPENED_ARG_COPY]]
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -182,6 +181,34 @@
 }
 // CHECK: } // end sil function '_T014dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F'
 
+// GUARANTEED-LABEL: sil hidden @_T014dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F
+  // GUARANTEED: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+  // GUARANTEED:   [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+  // GUARANTEED:   [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+  // GUARANTEED:   [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+  // GUARANTEED:   [[OBJ_COPY:%.*]] = copy_value [[BORROWED_OBJ]]
+  // GUARANTEED:   store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+  // GUARANTEED:   end_borrow [[BORROWED_OBJ]] from [[OBJ]]
+  // GUARANTEED:   [[INT_BOX:%[0-9]+]] = alloc_box ${ var Int }
+  // GUARANTEED:   project_box [[INT_BOX]]
+  // GUARANTEED:   [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+  // GUARANTEED:   [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+  // GUARANTEED:   [[RAWOBJ_SELF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject
+  // GUARANTEED:   [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+  // GUARANTEED:   dynamic_method_br [[RAWOBJ_SELF]] : $@opened({{.*}}) AnyObject, #X.value!getter.1.foreign, bb1, bb2
+
+  // GUARANTEED: bb1([[METHOD:%[0-9]+]] : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> Int):
+  // GUARANTEED:   [[RAWOBJ_SELF_COPY:%.*]] = copy_value [[RAWOBJ_SELF]]
+  // GUARANTEED:   [[BOUND_METHOD:%[0-9]+]] = partial_apply [callee_guaranteed] [[METHOD]]([[RAWOBJ_SELF_COPY]])
+  // GUARANTEED:   [[BEGIN_BORROW:%.*]] = begin_borrow [[BOUND_METHOD]]
+  // GUARANTEED:   [[VALUE:%[0-9]+]] = apply [[BEGIN_BORROW]]
+  // GUARANTEED:   end_borrow [[BEGIN_BORROW]] from [[BOUND_METHOD]]
+  // GUARANTEED:   [[VALUETEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+  // GUARANTEED:   store [[VALUE]] to [trivial] [[VALUETEMP]]
+  // GUARANTEED:   inject_enum_addr [[OPTTEMP]]{{.*}}some
+  // GUARANTEED:   destroy_value [[BOUND_METHOD]]
+  // GUARANTEED:   br bb3
+
 // CHECK-LABEL: sil hidden @_T014dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F
 func direct_to_subscript(_ obj: AnyObject, i: Int) {
   var obj = obj
@@ -218,6 +245,39 @@
 }
 // CHECK: } // end sil function '_T014dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F'
 
+// GUARANTEED-LABEL: sil hidden @_T014dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F
+  // GUARANTEED: bb0([[OBJ:%[0-9]+]] : $AnyObject, [[I:%[0-9]+]] : $Int):
+  // GUARANTEED:   [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+  // GUARANTEED:   [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+  // GUARANTEED:   [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+  // GUARANTEED:   [[OBJ_COPY:%.*]] = copy_value [[BORROWED_OBJ]]
+  // GUARANTEED:   store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+  // GUARANTEED:   end_borrow [[BORROWED_OBJ]] from [[OBJ]]
+  // GUARANTEED:   [[I_BOX:%[0-9]+]] = alloc_box ${ var Int }
+  // GUARANTEED:   [[PBI:%.*]] = project_box [[I_BOX]]
+  // GUARANTEED:   store [[I]] to [trivial] [[PBI]] : $*Int
+  // GUARANTEED:   alloc_box ${ var Int }
+  // GUARANTEED:   project_box
+  // GUARANTEED:   [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+  // GUARANTEED:   [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+  // GUARANTEED:   [[OBJ_REF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject to $@opened({{.*}}) AnyObject
+  // GUARANTEED:   [[READ:%.*]] = begin_access [read] [unknown] [[PBI]]
+  // GUARANTEED:   [[I:%[0-9]+]] = load [trivial] [[READ]] : $*Int
+  // GUARANTEED:   [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+  // GUARANTEED:   dynamic_method_br [[OBJ_REF]] : $@opened({{.*}}) AnyObject, #X.subscript!getter.1.foreign, bb1, bb2
+
+  // GUARANTEED: bb1([[GETTER:%[0-9]+]] : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int):
+  // GUARANTEED:   [[OBJ_REF_COPY:%.*]] = copy_value [[OBJ_REF]]
+  // GUARANTEED:   [[GETTER_WITH_SELF:%[0-9]+]] = partial_apply [callee_guaranteed] [[GETTER]]([[OBJ_REF_COPY]])
+  // GUARANTEED:   [[BORROW:%.*]] = begin_borrow [[GETTER_WITH_SELF]]
+  // GUARANTEED:   [[RESULT:%[0-9]+]] = apply [[BORROW]]([[I]])
+  // GUARANTEED:   end_borrow [[BORROW]] from [[GETTER_WITH_SELF]]
+  // GUARANTEED:   [[RESULTTEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+  // GUARANTEED:   store [[RESULT]] to [trivial] [[RESULTTEMP]]
+  // GUARANTEED:   inject_enum_addr [[OPTTEMP]]{{.*}}some
+  // GUARANTEED:   destroy_value [[GETTER_WITH_SELF]]
+  // GUARANTEED:   br bb3
+
 // CHECK-LABEL: sil hidden @_T014dynamic_lookup16opt_to_subscript{{[_0-9a-zA-Z]*}}F
 func opt_to_subscript(_ obj: AnyObject, i: Int) {
   var obj = obj
diff --git a/test/SILGen/dynamic_lookup_throws.swift b/test/SILGen/dynamic_lookup_throws.swift
index af96fda..29780ae 100644
--- a/test/SILGen/dynamic_lookup_throws.swift
+++ b/test/SILGen/dynamic_lookup_throws.swift
@@ -17,8 +17,7 @@
   // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK:   [[ANYOBJECT_REF:%.*]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened("[[OPENED:.*]]") AnyObject
   // CHECK:   [[ANYOBJECT_REF_COPY:%.*]] = copy_value [[ANYOBJECT_REF]]
-  // CHECK:   [[BORROWED_ANYOBJECT_REF_COPY:%.*]] = begin_borrow [[ANYOBJECT_REF_COPY]]
-  // CHECK:   objc_method [[BORROWED_ANYOBJECT_REF_COPY]] : $@opened("[[OPENED]]") AnyObject, #Blub.blub!1.foreign : (Blub) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @opened("[[OPENED]]") AnyObject) -> ObjCBool
+  // CHECK:   objc_method [[ANYOBJECT_REF_COPY]] : $@opened("[[OPENED]]") AnyObject, #Blub.blub!1.foreign : (Blub) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @opened("[[OPENED]]") AnyObject) -> ObjCBool
   // CHECK:   cond_br {{%.*}}, bb1, bb2
 
   // CHECK: bb1
diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift
index 078fba2..0186d2b 100644
--- a/test/SILGen/dynamic_self.swift
+++ b/test/SILGen/dynamic_self.swift
@@ -43,9 +43,9 @@
 // CHECK:   [[BORROWED_Y_AS_X:%[0-9]+]] = upcast [[BORROWED_Y]] : $Y to $X
 // CHECK:   [[X_F:%[0-9]+]] = class_method [[BORROWED_Y_AS_X]] : $X, #X.f!1 : (X) -> () -> @dynamic_self X, $@convention(method) (@guaranteed X) -> @owned X
 // CHECK:   [[X_RESULT:%[0-9]+]] = apply [[X_F]]([[BORROWED_Y_AS_X]]) : $@convention(method) (@guaranteed X) -> @owned X
+// CHECK:   end_borrow [[BORROWED_Y]] from [[Y]]
 // CHECK:   [[Y_RESULT:%[0-9]+]] = unchecked_ref_cast [[X_RESULT]] : $X to $Y
 // CHECK:   destroy_value [[Y_RESULT]] : $Y
-// CHECK:   end_borrow [[BORROWED_Y]] from [[Y]]
 // CHECK:   destroy_value [[Y]] : $Y
 func testDynamicSelfDispatch(y: Y) {
   _ = y.f()
@@ -58,9 +58,9 @@
   // CHECK:   [[BORROWED_GY_AS_GX:%[0-9]+]] = upcast [[BORROWED_GY]] : $GY<Int> to $GX<Array<Int>>
   // CHECK:   [[GX_F:%[0-9]+]] = class_method [[BORROWED_GY_AS_GX]] : $GX<Array<Int>>, #GX.f!1 : <T> (GX<T>) -> () -> @dynamic_self GX<T>, $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
   // CHECK:   [[GX_RESULT:%[0-9]+]] = apply [[GX_F]]<[Int]>([[BORROWED_GY_AS_GX]]) : $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
+  // CHECK:   end_borrow [[BORROWED_GY]] from [[GY]]
   // CHECK:   [[GY_RESULT:%[0-9]+]] = unchecked_ref_cast [[GX_RESULT]] : $GX<Array<Int>> to $GY<Int>
   // CHECK:   destroy_value [[GY_RESULT]] : $GY<Int>
-  // CHECK:   end_borrow [[BORROWED_GY]] from [[GY]]
   // CHECK:   destroy_value [[GY]]
   _ = gy.f()
 }
@@ -68,8 +68,8 @@
 // CHECK-LABEL: sil hidden @_T012dynamic_self21testArchetypeDispatch{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : P> (@in T) -> ()
 func testArchetypeDispatch<T: P>(t: T) {
   // CHECK: bb0([[T:%[0-9]+]] : $*T):
-  // CHECK:   [[ARCHETYPE_F:%[0-9]+]] = witness_method $T, #P.f!1 : {{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK:   [[T_RESULT:%[0-9]+]] = alloc_stack $T
+  // CHECK:   [[ARCHETYPE_F:%[0-9]+]] = witness_method $T, #P.f!1 : {{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK:   [[SELF_RESULT:%[0-9]+]] = apply [[ARCHETYPE_F]]<T>([[T_RESULT]], [[T]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   _ = t.f()
 }
@@ -128,8 +128,7 @@
 // CHECK: bb0([[THICK_META:%[0-9]+]] : $@thick ObjCInit.Type):
 // CHECK:   [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[THICK_META]] : $@thick ObjCInit.Type to $@objc_metatype ObjCInit.Type
 // CHECK:   [[OBJ:%[0-9]+]] = alloc_ref_dynamic [objc] [[OBJC_META]] : $@objc_metatype ObjCInit.Type, $ObjCInit
-// CHECK:   [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
-// CHECK:   [[INIT:%[0-9]+]] = objc_method [[BORROWED_OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
+// CHECK:   [[INIT:%[0-9]+]] = objc_method [[OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
 // CHECK:   [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[OBJ]]) : $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
 // CHECK:   [[RESULT:%[0-9]+]] = tuple ()
 // CHECK:   return [[RESULT]] : $()
@@ -162,6 +161,7 @@
 // CHECK:      [[CAST_BORROWED_ARG:%.*]] = upcast [[BORROWED_ARG]]
 // CHECK:      [[T0:%.*]] = class_method [[CAST_BORROWED_ARG]] : $OptionalResult, #OptionalResult.foo!1 : (OptionalResult) -> () -> @dynamic_self OptionalResult?, $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult>
 // CHECK-NEXT: [[RES:%.*]] = apply [[T0]]([[CAST_BORROWED_ARG]])
+// CHECK-NEXT: end_borrow [[BORROWED_ARG]]
 // CHECK-NEXT: [[T4:%.*]] = unchecked_ref_cast [[RES]] : $Optional<OptionalResult> to $Optional<OptionalResultInheritor>
 
 func id<T>(_ t: T) -> T { return t }
diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift
index 85fa5cb..1ffc32e 100644
--- a/test/SILGen/enum.swift
+++ b/test/SILGen/enum.swift
@@ -33,8 +33,8 @@
 // CHECK-LABEL: sil hidden @_T0s16Optionable_casesySiF
 func Optionable_cases(_ x: Int) {
 
+  // CHECK:       [[METATYPE:%.*]] = metatype $@thin Optionable.Type
   // CHECK:       [[FN:%.*]] = function_ref @_T0s10OptionableO4mereABSicABmF
-  // CHECK-NEXT:  [[METATYPE:%.*]] = metatype $@thin Optionable.Type
   // CHECK-NEXT:  [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
   // CHECK-NEXT:  destroy_value [[CTOR]]
   _ = Optionable.mere
@@ -67,8 +67,8 @@
 // CHECK-LABEL: sil hidden @_T0s17AddressOnly_casesys1SVF
 func AddressOnly_cases(_ s: S) {
 
+  // CHECK:       [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
   // CHECK:       [[FN:%.*]] = function_ref @_T0s11AddressOnlyO4mereABs1P_pcABmF
-  // CHECK-NEXT:  [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
   // CHECK-NEXT:  [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
   // CHECK-NEXT:  destroy_value [[CTOR]]
   _ = AddressOnly.mere
diff --git a/test/SILGen/enum_resilience.swift b/test/SILGen/enum_resilience.swift
index d586136..41a265e 100644
--- a/test/SILGen/enum_resilience.swift
+++ b/test/SILGen/enum_resilience.swift
@@ -52,3 +52,30 @@
 
 // CHECK-LABEL: sil hidden @_T015enum_resilience21indirectResilientEnumy010resilient_A016IndirectApproachOF : $@convention(thin) (@in IndirectApproach) -> ()
 func indirectResilientEnum(_ ia: IndirectApproach) {}
+
+public enum MyResilientEnum {
+  case kevin
+  case loki
+}
+
+// CHECK-LABEL: sil @_T015enum_resilience15resilientSwitchyAA15MyResilientEnumOF : $@convention(thin) (@in MyResilientEnum) -> ()
+// CHECK:      switch_enum_addr %2 : $*MyResilientEnum, case #MyResilientEnum.kevin!enumelt: bb1, case #MyResilientEnum.loki!enumelt: bb2 //
+// CHECK:      return
+public func resilientSwitch(_ e: MyResilientEnum) {
+  switch e {
+  case .kevin: ()
+  case .loki: ()
+  }
+}
+
+// Inlineable functions must lower the switch as if it came from outside the module
+
+// CHECK-LABEL: sil [serialized] @_T015enum_resilience16inlineableSwitchyAA15MyResilientEnumOF : $@convention(thin) (@in MyResilientEnum) -> ()
+// CHECK:      switch_enum_addr %2 : $*MyResilientEnum, case #MyResilientEnum.kevin!enumelt: bb1, case #MyResilientEnum.loki!enumelt: bb2, default bb3
+// CHECK:      return
+@_inlineable public func inlineableSwitch(_ e: MyResilientEnum) {
+  switch e {
+  case .kevin: ()
+  case .loki: ()
+  }
+}
diff --git a/test/SILGen/errors.swift b/test/SILGen/errors.swift
index 3855c28..ff2ae57 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -14,8 +14,8 @@
 func someValidPointer<T>() -> UnsafeMutablePointer<T> { fatalError() }
 
 // CHECK: sil hidden @_T06errors10make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error Error) {
+// CHECK:      [[T1:%.*]] = metatype $@thick Cat.Type 
 // CHECK:      [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
-// CHECK-NEXT: [[T1:%.*]] = metatype $@thick Cat.Type 
 // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
 // CHECK-NEXT: return [[T2]] : $Cat
 func make_a_cat() throws -> Cat {
@@ -49,8 +49,7 @@
 
 // CHECK:    sil hidden @_T06errors16all_together_nowAA3CatCSbF : $@convention(thin) (Bool) -> @owned Cat {
 // CHECK:    bb0(%0 : @trivial $Bool):
-// CHECK:      [[DR_FN:%.*]] = function_ref @_T06errors11dont_return{{.*}} :
-// CHECK-NEXT: [[RET_TEMP:%.*]] = alloc_stack $Cat
+// CHECK:      [[RET_TEMP:%.*]] = alloc_stack $Cat
 
 //   Branch on the flag.
 // CHECK:      cond_br {{%.*}}, [[FLAG_TRUE:bb[0-9]+]], [[FLAG_FALSE:bb[0-9]+]]
@@ -73,6 +72,7 @@
 // CHECK:    [[TERNARY_CONT]]([[T0:%.*]] : @owned $Cat):
 // CHECK-NEXT: [[ARG_TEMP:%.*]] = alloc_stack $Cat
 // CHECK-NEXT: store [[T0]] to [init] [[ARG_TEMP]]
+// CHECK:      [[DR_FN:%.*]] = function_ref @_T06errors11dont_return{{.*}} :
 // CHECK-NEXT: try_apply [[DR_FN]]<Cat>([[RET_TEMP]], [[ARG_TEMP]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[DR_NORMAL:bb[0-9]+]], error [[DR_ERROR:bb[0-9]+]]
 // CHECK:    [[DR_NORMAL]]({{%.*}} : @trivial $()):
 // CHECK-NEXT: dealloc_stack [[ARG_TEMP]]
@@ -132,8 +132,8 @@
 
 //   Catch all.
 // CHECK:    [[CATCHALL]]:
-// CHECK:      [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
 // CHECK-NEXT: [[T1:%.*]] = metatype $@thick Cat.Type
+// CHECK:      [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
 // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
 // CHECK-NEXT: end_borrow [[BORROWED_ERROR]] from [[ERROR]]
 // CHECK-NEXT: destroy_value [[ERROR]] : $Error
@@ -163,8 +163,8 @@
 //   Catch in non-throwing context.
 // CHECK-LABEL: sil hidden @_T06errors11catch_a_catAA3CatCyF : $@convention(thin) () -> @owned Cat
 // CHECK-NEXT: bb0:
-// CHECK:      [[F:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
 // CHECK-NEXT: [[M:%.*]] = metatype $@thick Cat.Type
+// CHECK:      [[F:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
 // CHECK-NEXT: [[V:%.*]] = apply [[F]]([[M]])
 // CHECK-NEXT: return [[V]] : $Cat
 func catch_a_cat() -> Cat {
@@ -323,9 +323,9 @@
 }
 // CHECK-LABEL: sil hidden @_T06errors12testForceTryySiycF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> ()
 // CHECK: bb0([[ARG:%.*]] : @owned $@noescape @callee_owned () -> Int):
-// CHECK: [[FUNC:%.*]] = function_ref @_T06errors9createIntySiycKF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> @error Error
 // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+// CHECK: [[FUNC:%.*]] = function_ref @_T06errors9createIntySiycKF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> @error Error
 // CHECK: try_apply [[FUNC]]([[ARG_COPY]])
 // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
 // CHECK: destroy_value [[ARG]]
@@ -423,7 +423,6 @@
 // CHECK-LABEL: sil hidden @_T06errors13test_variadicyAA3CatCKF : $@convention(thin) (@owned Cat) -> @error Error {
 // CHECK:       bb0([[ARG:%.*]] : @owned $Cat):
 // CHECK:         debug_value undef : $Error, var, name "$error", argno 2
-// CHECK:         [[TAKE_FN:%.*]] = function_ref @_T06errors14take_many_catsyAA3CatCd_tKF : $@convention(thin) (@owned Array<Cat>) -> @error Error
 // CHECK:         [[N:%.*]] = integer_literal $Builtin.Word, 4
 // CHECK:         [[T0:%.*]] = function_ref @_T0s27_allocateUninitializedArray{{.*}}F
 // CHECK:         [[T1:%.*]] = apply [[T0]]<Cat>([[N]])
@@ -462,6 +461,7 @@
 // CHECK:       [[NORM_3]]([[CAT3:%.*]] : @owned $Cat):
 // CHECK-NEXT:    store [[CAT3]] to [init] [[ELT3]]
 //   Complete the call and return.
+// CHECK:         [[TAKE_FN:%.*]] = function_ref @_T06errors14take_many_catsyAA3CatCd_tKF : $@convention(thin) (@owned Array<Cat>) -> @error Error
 // CHECK-NEXT:    try_apply [[TAKE_FN]]([[ARRAY]]) : $@convention(thin) (@owned Array<Cat>) -> @error Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]]
 // CHECK:       [[NORM_CALL]]([[T0:%.*]] : @trivial $()):
 // CHECK-NEXT:    end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -544,7 +544,6 @@
   try b.firstStructure.support()
 }
 // CHECK-LABEL: sil hidden @_T06errors21supportFirstStructure{{.*}}F : $@convention(thin) <B where B : Buildable> (@inout B) -> @error Error {
-// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
 // CHECK: [[MATBUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
 // CHECK: [[BUFFER:%.*]] = alloc_stack $B.Structure
 // CHECK: [[BUFFER_CAST:%.*]] = address_to_pointer [[BUFFER]] : $*B.Structure to $Builtin.RawPointer
@@ -554,6 +553,7 @@
 // CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
 // CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
 // CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
 // CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 
 // CHECK: [[BB_NORMAL]]
@@ -575,7 +575,6 @@
 }
 // CHECK-LABEL: sil hidden @_T06errors16supportStructure{{.*}}F
 // CHECK: bb0({{.*}}, [[INDEX:%.*]] : @owned $String):
-// CHECK:   [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
 // CHECK:   [[BORROWED_INDEX:%.*]] = begin_borrow [[INDEX]]
 // CHECK:   [[INDEX_COPY:%.*]] = copy_value [[BORROWED_INDEX]] : $String
 // CHECK:   [[MATBUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
@@ -587,6 +586,7 @@
 // CHECK:   [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
 // CHECK:   [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
 // CHECK:   [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK:   [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
 // CHECK:   try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 
 // CHECK: [[BB_NORMAL]]
@@ -625,8 +625,7 @@
 }
 // CHECK:    sil hidden @_T06errors16supportStructureyAA6BridgeVz_SS4nametKF : $@convention(thin) (@inout Bridge, @owned String) -> @error Error {
 // CHECK:    bb0([[ARG1:%.*]] : @trivial $*Bridge, [[ARG2:%.*]] : @owned $String):
-// CHECK:      [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
-// CHECK-NEXT: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
+// CHECK:      [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
 // CHECK-NEXT: [[INDEX_COPY_1:%.*]] = copy_value [[BORROWED_ARG2]] : $String
 // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*Bridge
 // CHECK-NEXT: [[INDEX_COPY_2:%.*]] = copy_value [[INDEX_COPY_1]] : $String
@@ -637,6 +636,7 @@
 // CHECK-NEXT: [[T0:%.*]] = apply [[GETTER]]([[INDEX_COPY_1]], [[BASE]])
 // CHECK-NEXT: store [[T0]] to [init] [[TEMP]]
 // CHECK-NEXT: end_borrow [[BASE]] from [[WRITE]]
+// CHECK:      [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
 // CHECK-NEXT: try_apply [[SUPPORT]]([[TEMP]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 
 // CHECK:    [[BB_NORMAL]]
@@ -681,7 +681,6 @@
 }
 // CHECK:    sil hidden @_T06errors16supportStructureyAA11OwnedBridgeVz_SS4nametKF :
 // CHECK:    bb0([[ARG1:%.*]] : @trivial $*OwnedBridge, [[ARG2:%.*]] : @owned $String):
-// CHECK:      [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
 // CHECK:      [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
 // CHECK:      [[ARG2_COPY:%.*]] = copy_value [[BORROWED_ARG2]] : $String
 // CHECK:      [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*OwnedBridge
@@ -697,6 +696,7 @@
 // CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
 // CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK:      [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
 // CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 // CHECK:    [[BB_NORMAL]]
 // CHECK-NEXT: end_access [[WRITE]]
@@ -725,7 +725,6 @@
 }
 // CHECK:      sil hidden @_T06errors16supportStructureyAA12PinnedBridgeVz_SS4nametKF :
 // CHECK:      bb0([[ARG1:%.*]] : @trivial $*PinnedBridge, [[ARG2:%.*]] : @owned $String):
-// CHECK:        [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
 // CHECK:        [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
 // CHECK:        [[ARG2_COPY:%.*]] = copy_value [[BORROWED_ARG2]] : $String
 // CHECK-NEXT:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*PinnedBridge
@@ -741,6 +740,7 @@
 // CHECK-NEXT:   [[T3:%.*]] = struct_extract [[T1]]
 // CHECK-NEXT:   [[T4:%.*]] = pointer_to_address [[T3]]
 // CHECK-NEXT:   [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK:        [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
 // CHECK-NEXT:   try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
 // CHECK:      [[BB_NORMAL]]
 // CHECK-NEXT:   strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
@@ -828,9 +828,9 @@
 // CHECK: bb0(%0 : @trivial $*T):
 // CHECK: [[BOX:%.+]] = alloc_stack $Optional<T>
 // CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[BOX]] : $*Optional<T>, #Optional.some!enumelt.1
-// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
 // CHECK-NEXT: [[ARG_BOX:%.+]] = alloc_stack $T
 // CHECK-NEXT: copy_addr %0 to [initialization] [[ARG_BOX]] : $*T
+// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
 // CHECK-NEXT: try_apply [[FN]]<T>([[BOX_DATA]], [[ARG_BOX]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]],
 // CHECK: [[SUCCESS]]({{%.+}} : @trivial $()):
 // CHECK-NEXT: dealloc_stack [[ARG_BOX]] : $*T
@@ -859,9 +859,9 @@
 // CHECK: [[BOX:%.+]] = alloc_box $<τ_0_0> { var Optional<τ_0_0> } <T>
 // CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
 // CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[PB]] : $*Optional<T>, #Optional.some!enumelt.1
-// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
 // CHECK-NEXT: [[ARG_BOX:%.+]] = alloc_stack $T
 // CHECK-NEXT: copy_addr %0 to [initialization] [[ARG_BOX]] : $*T
+// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
 // CHECK-NEXT: try_apply [[FN]]<T>([[BOX_DATA]], [[ARG_BOX]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]],
 // CHECK: [[SUCCESS]]({{%.+}} : @trivial $()):
 // CHECK-NEXT: dealloc_stack [[ARG_BOX]] : $*T
diff --git a/test/SILGen/existential_erasure.swift b/test/SILGen/existential_erasure.swift
index 0f3cba1..3b2eebb 100644
--- a/test/SILGen/existential_erasure.swift
+++ b/test/SILGen/existential_erasure.swift
@@ -44,11 +44,11 @@
 // CHECK:   [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[OPEN_TYPE:@opened\(.*\) P]]
 // CHECK:   [[RESULT:%.*]] = alloc_stack $P
 // CHECK:   [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*P, $[[OPEN_TYPE]]
-// CHECK:   [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.downgrade!1 : {{.*}}, [[OPEN]]
 // CHECK:   [[FUNC:%.*]] = function_ref @_T019existential_erasure12throwingFuncSbyKF
 // CHECK:   try_apply [[FUNC]]()
 //
 // CHECK: bb1([[SUCCESS:%.*]] : @trivial $Bool):
+// CHECK:   [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.downgrade!1 : {{.*}}, [[OPEN]]
 // CHECK:   apply [[METHOD]]<[[OPEN_TYPE]]>([[RESULT_ADDR]], [[SUCCESS]], [[OPEN]])
 // CHECK:   dealloc_stack [[RESULT]]
 // CHECK:   destroy_addr %0
diff --git a/test/SILGen/expressions.swift b/test/SILGen/expressions.swift
index a6934c6..89ca6d4 100644
--- a/test/SILGen/expressions.swift
+++ b/test/SILGen/expressions.swift
@@ -108,9 +108,9 @@
 }
 
 // CHECK-LABEL: sil hidden @_T011expressions8call_oneyyF
-// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int) -> ()
 // CHECK: [[FORTYTWO:%[0-9]+]] = integer_literal {{.*}} 42
 // CHECK: [[FORTYTWO_CONVERTED:%[0-9]+]] = apply {{.*}}([[FORTYTWO]], {{.*}})
+// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int) -> ()
 // CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]])
 
 func call_two() {
@@ -118,11 +118,11 @@
 }
 
 // CHECK-LABEL: sil hidden @_T011expressions8call_twoyyF
-// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Int) -> ()
 // CHECK: [[FORTYTWO:%[0-9]+]] = integer_literal {{.*}} 42
 // CHECK: [[FORTYTWO_CONVERTED:%[0-9]+]] = apply {{.*}}([[FORTYTWO]], {{.*}})
 // CHECK: [[TWONINETEEN:%[0-9]+]] = integer_literal {{.*}} 219
 // CHECK: [[TWONINETEEN_CONVERTED:%[0-9]+]] = apply {{.*}}([[TWONINETEEN]], {{.*}})
+// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Int) -> ()
 // CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]], [[TWONINETEEN_CONVERTED]])
 
 func tuples() {
@@ -206,21 +206,21 @@
 // CHECK-LABEL: sil hidden @_T011expressions19call_default_args_1{{[_0-9a-zA-Z]*}}F
 func call_default_args_1(_ x: Int) {
   default_args(x)
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
   // CHECK: [[YFUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A0_
   // CHECK: [[Y:%[0-9]+]] = apply [[YFUNC]]()
   // CHECK: [[ZFUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A1_
   // CHECK: [[Z:%[0-9]+]] = apply [[ZFUNC]]()
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC]]({{.*}}, [[Y]], [[Z]])
 }
 
 // CHECK-LABEL: sil hidden @_T011expressions19call_default_args_2{{[_0-9a-zA-Z]*}}F
 func call_default_args_2(_ x: Int, z: Int) {
   default_args(x, z:z)
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
   // CHECK: [[DEFFN:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A0_
   // CHECK-NEXT: [[C219:%[0-9]+]] = apply [[DEFFN]]()
-  // CHECK: apply [[FUNC]]({{.*}}, [[C219]], {{.*}})
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
+  // CHECK-NEXT: apply [[FUNC]]({{.*}}, [[C219]], {{.*}})
 }
 
 struct Generic<T> {
@@ -336,20 +336,20 @@
 func archetype_member_ref<T : Runcible>(_ x: T) {
   var x = x
   x.free_method()
-  // CHECK: witness_method $T, #Runcible.free_method!1
-  // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[X:%.*]]
+  // CHECK:      [[READ:%.*]] = begin_access [read] [unknown] [[X:%.*]]
   // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $T
   // CHECK-NEXT: copy_addr [[READ]] to [initialization] [[TEMP]]
   // CHECK-NEXT: end_access [[READ]]
+  // CHECK-NEXT: witness_method $T, #Runcible.free_method!1
   // CHECK-NEXT: apply
   // CHECK-NEXT: destroy_addr [[TEMP]]
   var u = x.associated_method()
-  // CHECK: witness_method $T, #Runcible.associated_method!1
-  // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown]
+  // CHECK:      [[WRITE:%.*]] = begin_access [modify] [unknown]
+  // CHECK-NEXT: witness_method $T, #Runcible.associated_method!1
   // CHECK-NEXT: apply
   T.static_method()
-  // CHECK: witness_method $T, #Runcible.static_method!1
-  // CHECK-NEXT: metatype $@thick T.Type
+  // CHECK:      metatype $@thick T.Type
+  // CHECK-NEXT: witness_method $T, #Runcible.static_method!1
   // CHECK-NEXT: apply
 }
 
diff --git a/test/SILGen/extensions.swift b/test/SILGen/extensions.swift
index 190c8eb..aa1fe8f 100644
--- a/test/SILGen/extensions.swift
+++ b/test/SILGen/extensions.swift
@@ -44,8 +44,8 @@
 
 // CHECK-LABEL: sil hidden [transparent] @_T010extensions3BoxV1txSgvpfi : $@convention(thin) <T> () -> @out Optional<T>
 // CHECK:      bb0(%0 : @trivial $*Optional<T>):
-// CHECK:      [[FN:%.*]] = function_ref @_T0SqxSgyt10nilLiteral_tcfC : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Optional<T>.Type
+// CHECK:      [[FN:%.*]] = function_ref @_T0SqxSgyt10nilLiteral_tcfC : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
 // CHECK-NEXT: apply [[FN]]<T>(%0, [[METATYPE]]) : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
 // CHECK-NEXT: [[RESULT:%.*]] = tuple ()
 // CHECK-NEXT: return [[RESULT]] : $()
diff --git a/test/SILGen/external_definitions.swift b/test/SILGen/external_definitions.swift
index 954b796..fb679f1 100644
--- a/test/SILGen/external_definitions.swift
+++ b/test/SILGen/external_definitions.swift
@@ -12,10 +12,10 @@
 
 // CHECK-LABEL: sil @main
 // -- Foreign function is referenced with C calling conv and ownership semantics
-// CHECK:   [[NSANSE:%.*]] = function_ref @NSAnse : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
-// CHECK:   [[ANSIBLE_CTOR:%.*]] = function_ref @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC
 // CHECK:   [[NSOBJECT_CTOR:%.*]] = function_ref @_T0So8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
+// CHECK:   [[ANSIBLE_CTOR:%.*]] = function_ref @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC
 // CHECK:   [[ANSIBLE:%.*]] = apply [[ANSIBLE_CTOR]]
+// CHECK:   [[NSANSE:%.*]] = function_ref @NSAnse : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
 // CHECK:   [[NSANSE_RESULT:%.*]] = apply [[NSANSE]]([[ANSIBLE]])
 // CHECK:   destroy_value [[ANSIBLE]] : $Optional<Ansible>
 // -- Referencing unapplied C function goes through a thunk
@@ -24,13 +24,12 @@
 // CHECK:   [[NOPROTO:%.*]] = function_ref @hasNoPrototype : $@convention(c) () -> ()
 // CHECK:   apply [[NOPROTO]]()
 
-// -- Constructors for imported Ansible
-// CHECK-LABEL: sil shared [serializable] @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Optional<Any>, @thick Ansible.Type) -> @owned Optional<Ansible>
-
-
 // -- Constructors for imported NSObject
 // CHECK-LABEL: sil shared [serializable] @_T0So8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
 
+// -- Constructors for imported Ansible
+// CHECK-LABEL: sil shared [serializable] @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Optional<Any>, @thick Ansible.Type) -> @owned Optional<Ansible>
+
 // -- Native Swift thunk for NSAnse
 // CHECK: sil shared [serialized] [thunk] @_T0SC6NSAnseSQySo7AnsibleCGADFTO : $@convention(thin) (@owned Optional<Ansible>) -> @owned Optional<Ansible> {
 // CHECK: bb0(%0 : @owned $Optional<Ansible>):
diff --git a/test/SILGen/final.swift b/test/SILGen/final.swift
index a6c6618..a25edc7 100644
--- a/test/SILGen/final.swift
+++ b/test/SILGen/final.swift
@@ -20,8 +20,8 @@
 
 // CHECK-LABEL: sil hidden @{{.*}}testDirectDispatch{{.*}} : $@convention(thin) (@owned TestClass) -> Int {
 // CHECK: bb0([[ARG:%.*]] : @owned $TestClass):
-// CHECK: [[FINALMETH:%[0-9]+]] = function_ref @_T05final9TestClassC0A6Method{{[_0-9a-zA-Z]*}}F
 // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// CHECK: [[FINALMETH:%[0-9]+]] = function_ref @_T05final9TestClassC0A6Method{{[_0-9a-zA-Z]*}}F
 // CHECK: apply [[FINALMETH]]([[BORROWED_ARG]])
 // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
 // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
diff --git a/test/SILGen/force_cast_chained_optional.swift b/test/SILGen/force_cast_chained_optional.swift
index 29cff95..c5ae257 100644
--- a/test/SILGen/force_cast_chained_optional.swift
+++ b/test/SILGen/force_cast_chained_optional.swift
@@ -26,7 +26,6 @@
 // CHECK:   [[BAR:%.*]] = load [copy] [[PAYLOAD_ADDR]]
 // CHECK:   [[BORROWED_BAR:%.*]] = begin_borrow [[BAR]]
 // CHECK:   [[METHOD:%.*]] = class_method [[BORROWED_BAR]] : $Bar, #Bar.bas!getter.1 : (Bar) -> () -> C!, $@convention(method) (@guaranteed Bar) ->
-// CHECK:   [[BORROWED_BAR:%.*]] = begin_borrow [[BAR]]
 // CHECK:   apply [[METHOD]]([[BORROWED_BAR]])
 // CHECK:   end_borrow [[BORROWED_BAR]] from [[BAR]]
 // CHECK:   unconditional_checked_cast {{%.*}} : $C to $D
diff --git a/test/SILGen/foreach.swift b/test/SILGen/foreach.swift
index 10a096d..bcbdbc9 100644
--- a/test/SILGen/foreach.swift
+++ b/test/SILGen/foreach.swift
@@ -109,17 +109,17 @@
 // CHECK: bb0([[ARRAY:%.*]] : @owned $Array<Int>):
 // CHECK:   [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<Int>> }, var, name "$x$generator"
 // CHECK:   [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
-// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
 // CHECK:   [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<Int>
 // CHECK:   store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   apply [[MAKE_ITERATOR_FUNC]]<[Int]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
 // CHECK:   br [[LOOP_DEST:bb[0-9]+]]
 //
 // CHECK: [[LOOP_DEST]]:
-// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   [[GET_ELT_STACK:%.*]] = alloc_stack $Optional<Int>
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<Int>>
+// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   apply [[FUNC_REF]]<[Int]>([[GET_ELT_STACK]], [[WRITE]])
 // CHECK:   [[IND_VAR:%.*]] = load [trivial] [[GET_ELT_STACK]]
 // CHECK:   switch_enum [[IND_VAR]] : $Optional<Int>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
@@ -214,17 +214,17 @@
 // CHECK: bb0([[ARRAY:%.*]] : @owned $Array<P>):
 // CHECK:   [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<P>> }, var, name "$x$generator"
 // CHECK:   [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
-// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
 // CHECK:   [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<P>
 // CHECK:   store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   apply [[MAKE_ITERATOR_FUNC]]<[P]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
 // CHECK:   [[ELT_STACK:%.*]] = alloc_stack $Optional<P>
 // CHECK:   br [[LOOP_DEST:bb[0-9]+]]
 //
 // CHECK: [[LOOP_DEST]]:
-// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<P>> // users: %16, %15
+// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   apply [[FUNC_REF]]<[P]>([[ELT_STACK]], [[WRITE]])
 // CHECK:   switch_enum_addr [[ELT_STACK]] : $*Optional<P>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
 //
@@ -379,17 +379,17 @@
 // CHECK: bb0([[ARRAY:%.*]] : @owned $Array<GenericStruct<T>>):
 // CHECK:   [[ITERATOR_BOX:%.*]] = alloc_box $<τ_0_0> { var IndexingIterator<Array<GenericStruct<τ_0_0>>> } <T>, var, name "$x$generator"
 // CHECK:   [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
-// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
 // CHECK:   [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<GenericStruct<T>>
 // CHECK:   store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK:   [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
 // CHECK:   apply [[MAKE_ITERATOR_FUNC]]<[GenericStruct<T>]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
 // CHECK:   [[ELT_STACK:%.*]] = alloc_stack $Optional<GenericStruct<T>>
 // CHECK:   br [[LOOP_DEST:bb[0-9]+]]
 //
 // CHECK: [[LOOP_DEST]]:
-// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<GenericStruct<T>>>
+// CHECK:   [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
 // CHECK:   apply [[FUNC_REF]]<[GenericStruct<T>]>([[ELT_STACK]], [[WRITE]])
 // CHECK:   switch_enum_addr [[ELT_STACK]] : $*Optional<GenericStruct<T>>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
 //
@@ -498,8 +498,8 @@
 // CHECK:   br [[LOOP_DEST:bb[0-9]+]]
 //
 // CHECK: [[LOOP_DEST]]:
-// CHECK:   [[GET_NEXT_FUNC:%.*]] = witness_method $T.Iterator, #IteratorProtocol.next!1 : <Self where Self : IteratorProtocol> (inout Self) -> () -> Self.Element? : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@inout τ_0_0) -> @out Optional<τ_0_0.Element>
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*T.Iterator
+// CHECK:   [[GET_NEXT_FUNC:%.*]] = witness_method $T.Iterator, #IteratorProtocol.next!1 : <Self where Self : IteratorProtocol> (inout Self) -> () -> Self.Element? : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@inout τ_0_0) -> @out Optional<τ_0_0.Element>
 // CHECK:   apply [[GET_NEXT_FUNC]]<T.Iterator>([[ELT_STACK]], [[WRITE]])
 // CHECK:   switch_enum_addr [[ELT_STACK]] : $*Optional<T.Element>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
 //
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index a3ed901..5b01bef 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -7,16 +7,14 @@
 import Foundation
 import errors
 
-// CHECK: sil hidden @_T014foreign_errors5test0yyKF : $@convention(thin) () -> @error Error
+// CHECK-LABEL: sil hidden @_T014foreign_errors5test0yyKF : $@convention(thin) () -> @error Error
 func test0() throws {
-  // CHECK: [[SELF:%.*]] = metatype $@thick ErrorProne.Type
-  // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@thick ErrorProne.Type, #ErrorProne.fail!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
-
   //   Create a strong temporary holding nil before we perform any further parts of function emission.
   // CHECK: [[ERR_TEMP0:%.*]] = alloc_stack $Optional<NSError>
   // CHECK: inject_enum_addr [[ERR_TEMP0]] : $*Optional<NSError>, #Optional.none!enumelt
 
-  // CHECK: [[OBJC_SELF:%.*]] = thick_to_objc_metatype [[SELF]]
+  // CHECK: [[SELF:%.*]] = metatype $@objc_metatype ErrorProne.Type
+  // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
 
   //   Create an unmanaged temporary, copy into it, and make a AutoreleasingUnsafeMutablePointer.
   // CHECK: [[ERR_TEMP1:%.*]] = alloc_stack $@sil_unmanaged Optional<NSError>
@@ -26,7 +24,7 @@
   // CHECK: address_to_pointer [[ERR_TEMP1]]
 
   //   Call the method.
-  // CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{.*}}, [[OBJC_SELF]])
+  // CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{.*}}, [[SELF]])
 
   //   Writeback to the first temporary.
   // CHECK: [[T0:%.*]] = load [trivial] [[ERR_TEMP1]]
@@ -73,9 +71,9 @@
 // CHECK:   [[T0:%.*]] = function_ref @swift_convertErrorToNSError : $@convention(thin) (@owned Error) -> @owned NSError
 // CHECK:   [[T1:%.*]] = apply [[T0]]([[ERR]])
 // CHECK:   [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
-// CHECK:   [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
 // CHECK:   [[TEMP:%.*]] = alloc_stack $Optional<NSError>
 // CHECK:   store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK:   [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
 // CHECK:   apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
 // CHECK:   dealloc_stack [[TEMP]]
 // CHECK:   br bb5
@@ -116,9 +114,9 @@
 // CHECK:   [[T0:%.*]] = function_ref @swift_convertErrorToNSError : $@convention(thin) (@owned Error) -> @owned NSError
 // CHECK:   [[T1:%.*]] = apply [[T0]]([[ERR]])
 // CHECK:   [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
-// CHECK:   [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
 // CHECK:   [[TEMP:%.*]] = alloc_stack $Optional<NSError>
 // CHECK:   store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK:   [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
 // CHECK:   apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
 // CHECK:   dealloc_stack [[TEMP]]
 // CHECK:   br bb5
@@ -167,16 +165,16 @@
 func testArgs() throws {
   try ErrorProne.consume(nil)
 }
-// CHECK: sil hidden @_T014foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error
+// CHECK-LABEL: sil hidden @_T014foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error
 // CHECK:   debug_value undef : $Error, var, name "$error", argno 1
-// CHECK:   objc_method %1 : $@thick ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any!) throws -> (), $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
+// CHECK:   objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any!) throws -> (), $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
 
 func testBridgedResult() throws {
   let array = try ErrorProne.collection(withCount: 0)
 }
 // CHECK-LABEL: sil hidden @_T014foreign_errors17testBridgedResultyyKF : $@convention(thin) () -> @error Error {
 // CHECK:   debug_value undef : $Error, var, name "$error", argno 1
-// CHECK:   objc_method %1 : $@thick ErrorProne.Type, #ErrorProne.collection!1.foreign : (ErrorProne.Type) -> (Int) throws -> [Any], $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional<NSArray>
+// CHECK:   objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.collection!1.foreign : (ErrorProne.Type) -> (Int) throws -> [Any], $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional<NSArray>
 
 // rdar://20861374
 // Clear out the self box before delegating.
@@ -198,14 +196,14 @@
 // CHECK:      store [[ARG2]] to [init] [[PB]]
 // CHECK:      [[T0:%.*]] = load [take] [[PB]]
 // CHECK-NEXT: [[T1:%.*]] = upcast [[T0]] : $VeryErrorProne to $ErrorProne
-// CHECK-NEXT: [[BORROWED_T1:%.*]] = begin_borrow [[T1]]
-// CHECK-NEXT: [[DOWNCAST_BORROWED_T1:%.*]] = unchecked_ref_cast [[BORROWED_T1]] : $ErrorProne to $VeryErrorProne
-// CHECK-NEXT: [[T2:%.*]] = objc_super_method [[DOWNCAST_BORROWED_T1]] : $VeryErrorProne, #ErrorProne.init!initializer.1.foreign : (ErrorProne.Type) -> (Any?) throws -> ErrorProne, $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned ErrorProne) -> @owned Optional<ErrorProne>
-// CHECK:      end_borrow [[BORROWED_T1]] from [[T1]]
 // CHECK:      [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
 // CHECK:      [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
 // CHECK-NOT:  [[BOX]]{{^[0-9]}}
 // CHECK-NOT:  [[PB]]{{^[0-9]}}
+// CHECK: [[BORROWED_T1:%.*]] = begin_borrow [[T1]]
+// CHECK-NEXT: [[DOWNCAST_BORROWED_T1:%.*]] = unchecked_ref_cast [[BORROWED_T1]] : $ErrorProne to $VeryErrorProne
+// CHECK-NEXT: [[T2:%.*]] = objc_super_method [[DOWNCAST_BORROWED_T1]] : $VeryErrorProne, #ErrorProne.init!initializer.1.foreign : (ErrorProne.Type) -> (Any?) throws -> ErrorProne, $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned ErrorProne) -> @owned Optional<ErrorProne>
+// CHECK:      end_borrow [[BORROWED_T1]] from [[T1]]
 // CHECK:      apply [[T2]]([[ARG1_COPY]], {{%.*}}, [[T1]])
 
 // rdar://21051021
@@ -229,17 +227,17 @@
 class ExtremelyErrorProne : ErrorProne {
   override func conflict3(_ obj: Any, error: ()) throws {}
 }
-// CHECK: sil hidden @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKF
-// CHECK: sil hidden [thunk] @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKFTo : $@convention(objc_method) (AnyObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, ExtremelyErrorProne) -> ObjCBool
+// CHECK-LABEL: sil hidden @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKF
+// CHECK-LABEL: sil hidden [thunk] @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKFTo : $@convention(objc_method) (AnyObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, ExtremelyErrorProne) -> ObjCBool
 
 // These conventions are usable because of swift_error. rdar://21715350
 func testNonNilError() throws -> Float {
   return try ErrorProne.bounce()
 }
-// CHECK: sil hidden @_T014foreign_errors15testNonNilErrorSfyKF :
-// CHECK:   [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.bounce!1.foreign : (ErrorProne.Type) -> () throws -> Float, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Float
+// CHECK-LABEL: sil hidden @_T014foreign_errors15testNonNilErrorSfyKF :
 // CHECK:   [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK:   [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.bounce!1.foreign : (ErrorProne.Type) -> () throws -> Float, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Float
 // CHECK:   [[RESULT:%.*]] = apply [[T1]](
 // CHECK:   assign {{%.*}} to [[OPTERR]]
 // CHECK:   [[T0:%.*]] = load [take] [[OPTERR]]
@@ -252,10 +250,10 @@
 func testPreservedResult() throws -> CInt {
   return try ErrorProne.ounce()
 }
-// CHECK: sil hidden @_T014foreign_errors19testPreservedResults5Int32VyKF
-// CHECK:   [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.ounce!1.foreign : (ErrorProne.Type) -> () throws -> Int32, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
+// CHECK-LABEL: sil hidden @_T014foreign_errors19testPreservedResults5Int32VyKF
 // CHECK:   [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK:   [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.ounce!1.foreign : (ErrorProne.Type) -> () throws -> Int32, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
 // CHECK:   [[RESULT:%.*]] = apply [[T1]](
 // CHECK:   [[T0:%.*]] = struct_extract [[RESULT]]
 // CHECK:   [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
@@ -271,9 +269,9 @@
 }
 
 // CHECK-LABEL: sil hidden @_T014foreign_errors26testPreservedResultBridgedSiyKF
-// CHECK:   [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.ounceWord!1.foreign : (ErrorProne.Type) -> () throws -> Int, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int
 // CHECK:   [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK:   [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.ounceWord!1.foreign : (ErrorProne.Type) -> () throws -> Int, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int
 // CHECK:   [[RESULT:%.*]] = apply [[T1]](
 // CHECK:   [[T0:%.*]] = struct_extract [[RESULT]]
 // CHECK:   [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
@@ -289,9 +287,9 @@
 }
 
 // CHECK-LABEL: sil hidden @_T014foreign_errors27testPreservedResultInvertedyyKF
-// CHECK:   [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.once!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
 // CHECK:   [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK:   [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK:   [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.once!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
 // CHECK:   [[RESULT:%.*]] = apply [[T1]](
 // CHECK:   [[T0:%.*]] = struct_extract [[RESULT]]
 // CHECK:   [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index d510fe5..d8d9294 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -109,23 +109,23 @@
   // CHECK: [[KBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 }
   // CHECK: [[KADDR:%.*]] = project_box [[KBOX]]
 
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
   // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
   // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
   // CHECK: apply [[FUNC]]([[I]], [[J]])
   standalone_function(i, j)
 
   // -- Curry 'self' onto struct method argument lists.
 
   // CHECK: [[ST_ADDR:%.*]] = alloc_box ${ var SomeStruct }
-  // CHECK: [[CTOR:%.*]] = function_ref @_T09functions10SomeStructV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
   // CHECK: [[METATYPE:%.*]] = metatype $@thin SomeStruct.Type
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%.*]] = load [trivial] [[READI]]
   // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
   // CHECK: [[J:%.*]] = load [trivial] [[READJ]]
+  // CHECK: [[CTOR:%.*]] = function_ref @_T09functions10SomeStructV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
   // CHECK: apply [[CTOR]]([[I]], [[J]], [[METATYPE]]) : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
   var st = SomeStruct(x: i, y: j)
 
@@ -140,22 +140,21 @@
 
   // CHECK: [[CBOX:%[0-9]+]] = alloc_box ${ var SomeClass }
   // CHECK: [[CADDR:%.*]] = project_box [[CBOX]]
-  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions9SomeClassC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
   // CHECK: [[META:%[0-9]+]] = metatype $@thick SomeClass.Type
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
   // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
   // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+  // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions9SomeClassC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
   // CHECK: [[C:%[0-9]+]] = apply [[FUNC]]([[I]], [[J]], [[META]])
   var c = SomeClass(x: i, y: j)
 
   // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
   // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
-  // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+  // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
   // CHECK: apply [[METHOD]]([[I]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -170,10 +169,9 @@
   // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
   // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
-  // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+  // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
   // CHECK: apply [[METHOD]]([[I]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -184,9 +182,9 @@
   // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
   // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
   // CHECK: [[META:%.*]] = value_metatype $@thick SomeClass.Type, [[C]]
-  // CHECK: [[METHOD:%[0-9]+]] = class_method [[META]] : {{.*}}, #SomeClass.static_method!1
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+  // CHECK: [[METHOD:%[0-9]+]] = class_method [[META]] : {{.*}}, #SomeClass.static_method!1
   // CHECK: apply [[METHOD]]([[I]], [[META]])
   type(of: c).static_method(i)
 
@@ -195,8 +193,8 @@
   // -- FIXME: class_method-ify class getters.
   // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
   // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
-  // CHECK: [[GETTER:%[0-9]+]] = class_method {{.*}} : $SomeClass, #SomeClass.someProperty!getter.1
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+  // CHECK: [[GETTER:%[0-9]+]] = class_method {{.*}} : $SomeClass, #SomeClass.someProperty!getter.1
   // CHECK: apply [[GETTER]]([[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -208,7 +206,6 @@
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[SETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.someProperty!setter.1 : (SomeClass) -> (Builtin.Int64) -> ()
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: apply [[SETTER]]([[I]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -222,7 +219,6 @@
   // CHECK: [[K:%[0-9]+]] = load [trivial] [[READK]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[GETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.subscript!getter.1 : (SomeClass) -> (Builtin.Int64, Builtin.Int64) -> Builtin.Int64, $@convention(method) (Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> Builtin.Int64
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: apply [[GETTER]]([[J]], [[K]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -238,7 +234,6 @@
   // CHECK: [[K:%[0-9]+]] = load [trivial] [[READK]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[SETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.subscript!setter.1 : (SomeClass) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> (), $@convention(method) (Builtin.Int64, Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> ()
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: apply [[SETTER]]([[K]], [[I]], [[J]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -255,18 +250,18 @@
   // CHECK: [[TEMP:%.*]] = alloc_stack $SomeProtocol
   // CHECK: copy_addr [[READ]] to [initialization] [[TEMP]]
   // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
-  // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+  // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
   // CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
   // CHECK: destroy_addr [[TEMP]]
   // CHECK: dealloc_stack [[TEMP]]
   p.method(i)
 
   // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[PADDR:%.*]] : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
-  // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
   // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+  // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
   // CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
   var sp : SomeProtocol = ConformsToSomeProtocol()
   sp.method(i)
@@ -281,42 +276,39 @@
 
   // CHECK: [[GBOX:%[0-9]+]] = alloc_box ${ var SomeGeneric<Builtin.Int64> }
   // CHECK: [[GADDR:%.*]] = project_box [[GBOX]]
-  // CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @_T09functions11SomeGenericC{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@thick SomeGeneric<τ_0_0>.Type) -> @owned SomeGeneric<τ_0_0>
   // CHECK: [[META:%[0-9]+]] = metatype $@thick SomeGeneric<Builtin.Int64>.Type
+  // CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @_T09functions11SomeGenericC{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@thick SomeGeneric<τ_0_0>.Type) -> @owned SomeGeneric<τ_0_0>
   // CHECK: apply [[CTOR_GEN]]<Builtin.Int64>([[META]])
   var g = SomeGeneric<Builtin.Int64>()
 
+  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
   // CHECK: [[READG:%.*]] = begin_access [read] [unknown] [[GADDR]]
   // CHECK: [[G:%[0-9]+]] = load [copy] [[READG]]
   // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
-  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.method!1
-  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
-  // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK: [[TMPI:%.*]] = alloc_stack $Builtin.Int64
+  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.method!1
   // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPI]], [[BORROWED_G]])
   // CHECK: end_borrow [[BORROWED_G]] from [[G]]
   // CHECK: destroy_value [[G]]
   g.method(i)
 
+  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
   // CHECK: [[READG:%.*]] = begin_access [read] [unknown] [[GADDR]]
   // CHECK: [[G:%[0-9]+]] = load [copy] [[READG]]
   // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
-  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.generic!1
-  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
-  // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK: [[TMPJ:%.*]] = alloc_stack $Builtin.Int64
+  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.generic!1
   // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPJ]], [[BORROWED_G]])
   // CHECK: end_borrow [[BORROWED_G]] from [[G]]
   // CHECK: destroy_value [[G]]
   g.generic(j)
 
+  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
   // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
   // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
   // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
-  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.generic!1
-  // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
-  // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
   // CHECK: [[TMPK:%.*]] = alloc_stack $Builtin.Int64
+  // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.generic!1
   // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPK]], [[BORROWED_C]])
   // CHECK: end_borrow [[BORROWED_C]] from [[C]]
   // CHECK: destroy_value [[C]]
@@ -350,7 +342,6 @@
   // CHECK: apply [[F]]([[I]], [[J]])
   f(i, j)
 
-  // CHECK: [[HOF:%[0-9]+]] = function_ref @_T09functions21higher_order_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
   // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_T09functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
   // CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
   // CHECK: [[CONVERT:%.*]] = convert_function [[FUNC_THICK]]
@@ -358,10 +349,10 @@
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
   // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
   // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+  // CHECK: [[HOF:%[0-9]+]] = function_ref @_T09functions21higher_order_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
   // CHECK: apply [[HOF]]([[CONVERT]], [[I]], [[J]])
   higher_order_function(standalone_function, i, j)
 
-  // CHECK: [[HOF2:%[0-9]+]] = function_ref @_T09functions22higher_order_function2{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
   // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_T09functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
   // CHECK: [[FUNC_THICK:%.*]] = thin_to_thick_function [[FUNC_THIN]]
   // CHECK: [[CONVERT:%.*]] = convert_function [[FUNC_THICK]]
@@ -369,6 +360,7 @@
   // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
   // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
   // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+  // CHECK: [[HOF2:%[0-9]+]] = function_ref @_T09functions22higher_order_function2{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
   // CHECK: apply [[HOF2]]([[CONVERT]], [[I]], [[J]])
   higher_order_function2(standalone_function, i, j)
 }
@@ -460,6 +452,37 @@
   func alwaysInlined() {}
 }
 
+// CHECK-LABEL: sil hidden [Onone] @_T09functions10onone_funcyyF : $@convention(thin) () -> ()
+@_optimize(none)
+func onone_func() {}
+
+// CHECK-LABEL: sil hidden [Ospeed] @_T09functions11ospeed_funcyyF : $@convention(thin) () -> ()
+@_optimize(speed)
+func ospeed_func() {}
+
+// CHECK-LABEL: sil hidden [Osize] @_T09functions10osize_funcyyF : $@convention(thin) () -> ()
+@_optimize(size)
+func osize_func() {}
+
+struct OptmodeTestStruct {
+
+  // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV3fooyyF :
+  @_optimize(speed)
+  func foo() { }
+
+  // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVACycfC :
+  @_optimize(speed)
+  init() { }
+
+  // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV1xBi64_vg :
+  @_optimize(speed)
+  var x: Int { return getInt() }
+
+  // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVBi64_Bi64_cig :
+  @_optimize(speed)
+  subscript(l: Int) -> Int { return getInt() }
+}
+
 // CHECK-LABEL: sil hidden [_semantics "foo"] @_T09functions9semanticsyyF : $@convention(thin) () -> ()
 @_semantics("foo")
 func semantics() {}
diff --git a/test/SILGen/generic_literals.swift b/test/SILGen/generic_literals.swift
index 5607de8..d0af2f4 100644
--- a/test/SILGen/generic_literals.swift
+++ b/test/SILGen/generic_literals.swift
@@ -3,14 +3,14 @@
 // CHECK-LABEL: sil hidden @_T016generic_literals0A14IntegerLiteralyx1x_ts013ExpressibleBycD0RzlF
 func genericIntegerLiteral<T : ExpressibleByIntegerLiteral>(x: T) {
   var x = x
-  // CHECK: [[TCONV:%.*]] = witness_method $T, #ExpressibleByIntegerLiteral.init!allocator.1
   // CHECK: [[ADDR:%.*]] = alloc_stack $T
   // CHECK: [[TMETA:%.*]] = metatype $@thick T.Type
-  // CHECK: [[BUILTINCONV:%.*]] = witness_method $T.IntegerLiteralType, #_ExpressibleByBuiltinIntegerLiteral.init!allocator.1
   // CHECK: [[LITVAR:%.*]] = alloc_stack $T.IntegerLiteralType
   // CHECK: [[LITMETA:%.*]] = metatype $@thick T.IntegerLiteralType.Type
   // CHECK: [[INTLIT:%.*]] = integer_literal $Builtin.Int2048, 17
+  // CHECK: [[BUILTINCONV:%.*]] = witness_method $T.IntegerLiteralType, #_ExpressibleByBuiltinIntegerLiteral.init!allocator.1
   // CHECK: [[LIT:%.*]] = apply [[BUILTINCONV]]<T.IntegerLiteralType>([[LITVAR]], [[INTLIT]], [[LITMETA]]) : $@convention(witness_method: _ExpressibleByBuiltinIntegerLiteral) <τ_0_0 where τ_0_0 : _ExpressibleByBuiltinIntegerLiteral> (Builtin.Int2048, @thick τ_0_0.Type) -> @out τ_0_0
+  // CHECK: [[TCONV:%.*]] = witness_method $T, #ExpressibleByIntegerLiteral.init!allocator.1
   // CHECK: apply [[TCONV]]<T>([[ADDR]], [[LITVAR]], [[TMETA]]) : $@convention(witness_method: ExpressibleByIntegerLiteral) <τ_0_0 where τ_0_0 : ExpressibleByIntegerLiteral> (@in τ_0_0.IntegerLiteralType, @thick τ_0_0.Type) -> @out τ_0_0
 
   x = 17
@@ -19,14 +19,14 @@
 // CHECK-LABEL: sil hidden @_T016generic_literals0A15FloatingLiteral{{[_0-9a-zA-Z]*}}F
 func genericFloatingLiteral<T : ExpressibleByFloatLiteral>(x: T) {
   var x = x
-  // CHECK: [[CONV:%.*]] = witness_method $T, #ExpressibleByFloatLiteral.init!allocator.1
   // CHECK: [[TVAL:%.*]] = alloc_stack $T
   // CHECK: [[TMETA:%.*]] = metatype $@thick T.Type
-  // CHECK: [[BUILTIN_CONV:%.*]] = witness_method $T.FloatLiteralType, #_ExpressibleByBuiltinFloatLiteral.init!allocator.1
   // CHECK: [[FLT_VAL:%.*]] = alloc_stack $T.FloatLiteralType
   // CHECK: [[TFLT_META:%.*]] = metatype $@thick T.FloatLiteralType.Type
   // CHECK: [[LIT_VALUE:%.*]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x4004000000000000|0x4000A000000000000000}}
+  // CHECK: [[BUILTIN_CONV:%.*]] = witness_method $T.FloatLiteralType, #_ExpressibleByBuiltinFloatLiteral.init!allocator.1
   // CHECK: apply [[BUILTIN_CONV]]<T.FloatLiteralType>([[FLT_VAL]], [[LIT_VALUE]], [[TFLT_META]]) : $@convention(witness_method: _ExpressibleByBuiltinFloatLiteral) <τ_0_0 where τ_0_0 : _ExpressibleByBuiltinFloatLiteral> (Builtin.FPIEEE{{64|80}}, @thick τ_0_0.Type) -> @out τ_0_0
+  // CHECK: [[CONV:%.*]] = witness_method $T, #ExpressibleByFloatLiteral.init!allocator.1
   // CHECK: apply [[CONV]]<T>([[TVAL]], [[FLT_VAL]], [[TMETA]]) : $@convention(witness_method: ExpressibleByFloatLiteral) <τ_0_0 where τ_0_0 : ExpressibleByFloatLiteral> (@in τ_0_0.FloatLiteralType, @thick τ_0_0.Type) -> @out τ_0_0
 
   x = 2.5
diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift
index 016fb43..6ea050c 100644
--- a/test/SILGen/generic_property_base_lifetime.swift
+++ b/test/SILGen/generic_property_base_lifetime.swift
@@ -18,8 +18,8 @@
 // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:   [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
 // CHECK:   [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK:   [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!getter.1 : {{.*}}, [[PROJECTION]]
 // CHECK:   [[BORROWED_PROJECTION_COPY:%.*]] = begin_borrow [[PROJECTION_COPY]]
+// CHECK:   [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!getter.1 : {{.*}}, [[PROJECTION]]
 // CHECK:   [[RESULT:%.*]] = apply [[WITNESS_METHOD]]<@opened{{.*}}>([[BORROWED_PROJECTION_COPY]])
 // CHECK:   end_borrow [[BORROWED_PROJECTION_COPY]] from [[PROJECTION_COPY]]
 // CHECK:   destroy_value [[PROJECTION_COPY]]
@@ -36,8 +36,8 @@
 // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:   [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
 // CHECK:   [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK:   [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!setter.1 : {{.*}}, [[PROJECTION]]
 // CHECK:   [[BORROWED_PROJECTION_COPY:%.*]] = begin_borrow [[PROJECTION_COPY]]
+// CHECK:   [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!setter.1 : {{.*}}, [[PROJECTION]]
 // CHECK:   apply [[WITNESS_METHOD]]<@opened{{.*}}>({{%.*}}, [[BORROWED_PROJECTION_COPY]])
 // CHECK:   end_borrow [[BORROWED_PROJECTION_COPY]] from [[PROJECTION_COPY]]
 // CHECK:   destroy_value [[PROJECTION_COPY]]
diff --git a/test/SILGen/guaranteed_self.swift b/test/SILGen/guaranteed_self.swift
index d9c33c9..db83215 100644
--- a/test/SILGen/guaranteed_self.swift
+++ b/test/SILGen/guaranteed_self.swift
@@ -492,9 +492,9 @@
   // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[KRAKEN_ADDR]] : $*Kraken
   // CHECK-NEXT: [[KRAKEN:%.*]] = load [copy] [[READ]]
   // CHECK-NEXT: end_access [[READ]] : $*Kraken
-  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
-  // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+  // CHECK:      [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = copy_value [[BORROWED_KRAKEN]]
+  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
   // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
@@ -504,10 +504,10 @@
   // CHECK-NEXT: [[KRAKEN2:%.*]] = load [copy] [[READ]]
   // CHECK-NEXT: end_access [[READ]] : $*Kraken
   // CHECK-NEXT: store [[KRAKEN2]] to [init] [[PB]]
-  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
   // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[READ]]
   // CHECK-NEXT: end_access [[READ]] : $*Kraken
+  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
   // CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
   // CHECK-NEXT: destroy_value [[KRAKEN]]
@@ -527,16 +527,14 @@
   // CHECK-NEXT: [[KRAKEN:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
   // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_METH:%.*]] = class_method [[BORROWED_KRAKEN]]
-  // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
-  // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
   // CHECK-NEXT: apply [[KRAKEN_METH]]([[BORROWED_KRAKEN]])
   // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
   // CHECK-NEXT: destroy_value [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_GETTER_FUN:%.*]] = class_method [[CLS]] : $LetFieldClass, #LetFieldClass.vark!getter.1 : (LetFieldClass) -> () -> Kraken, $@convention(method) (@guaranteed LetFieldClass) -> @owned Kraken
   // CHECK-NEXT: [[KRAKEN:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
-  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
-  // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+  // CHECK:      [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = copy_value [[BORROWED_KRAKEN]]
+  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
   // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
   // CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
@@ -544,10 +542,10 @@
   // CHECK-NEXT: [[KRAKEN_GETTER_FUN:%.*]] = class_method [[CLS]] : $LetFieldClass, #LetFieldClass.vark!getter.1 : (LetFieldClass) -> () -> Kraken, $@convention(method) (@guaranteed LetFieldClass) -> @owned Kraken
   // CHECK-NEXT: [[KRAKEN2:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
   // CHECK-NEXT: store [[KRAKEN2]] to [init] [[PB]]
-  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: [[WRITE:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
   // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[WRITE]]
   // CHECK-NEXT: end_access [[WRITE]] : $*Kraken
+  // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
   // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
   // CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
   // CHECK-NEXT: destroy_value [[KRAKEN]]
diff --git a/test/SILGen/if_while_binding.swift b/test/SILGen/if_while_binding.swift
index c2d6a33..2df545e 100644
--- a/test/SILGen/if_while_binding.swift
+++ b/test/SILGen/if_while_binding.swift
@@ -22,9 +22,9 @@
   // CHECK:  br [[CONT:bb[0-9]+]]
   if let x = foo() {
   // CHECK: [[YES]]([[VAL:%[0-9]+]] : @owned $String):
-  // CHECK:   [[A:%.*]] = function_ref @_T016if_while_binding1a
   // CHECK:   [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
   // CHECK:   [[VAL_COPY:%.*]] = copy_value [[BORROWED_VAL]]
+  // CHECK:   [[A:%.*]] = function_ref @_T016if_while_binding1a
   // CHECK:   apply [[A]]([[VAL_COPY]])
   // CHECK:   end_borrow [[BORROWED_VAL]] from [[VAL]]
   // CHECK:   destroy_value [[VAL]]
@@ -47,9 +47,9 @@
   //
   // CHECK: [[YESX]]([[VAL:%[0-9]+]] : @owned $String):
   // CHECK:   debug_value [[VAL]] : $String, let, name "x"
-  // CHECK:   [[A:%.*]] = function_ref @_T016if_while_binding1a
   // CHECK:   [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
   // CHECK:   [[VAL_COPY:%.*]] = copy_value [[BORROWED_VAL]]
+  // CHECK:   [[A:%.*]] = function_ref @_T016if_while_binding1a
   // CHECK:   apply [[A]]([[VAL_COPY]])
   // CHECK:   end_borrow [[BORROWED_VAL]] from [[VAL]]
   // CHECK:   destroy_value [[VAL]]
@@ -286,7 +286,8 @@
   // CHECK: debug_value %0 : $Int, let, name "a"
   // CHECK: [[EQRESULT:%[0-9]+]] = apply {{.*}}(%0, %0{{.*}}) : $@convention({{.*}}) (Int, Int{{.*}}) -> Bool
 
-  // CHECK-NEXT: [[EQRESULTI1:%[0-9]+]] = apply %2([[EQRESULT]]) : $@convention(method) (Bool) -> Builtin.Int1
+  // CHECK:      [[FN:%.*]] = function_ref {{.*}}
+  // CHECK-NEXT: [[EQRESULTI1:%[0-9]+]] = apply [[FN:%.*]]([[EQRESULT]]) : $@convention(method) (Bool) -> Builtin.Int1
   // CHECK-NEXT: cond_br [[EQRESULTI1]], [[CHECKFOO:bb[0-9]+]], [[IFDONE:bb[0-9]+]]
 
   // Call Foo and test for the optional being present.
diff --git a/test/SILGen/import_as_member.swift b/test/SILGen/import_as_member.swift
index 868d379..6d4154a 100644
--- a/test/SILGen/import_as_member.swift
+++ b/test/SILGen/import_as_member.swift
@@ -45,8 +45,8 @@
   // CHECK: [[OBJ:%[0-9]+]] = apply [[CTOR]]([[D]])
   let o = SomeClass(value: d)
 
-  // CHECK: [[APPLY_FN:%[0-9]+]] = function_ref @IAMSomeClassApplyOptions : $@convention(c) (SomeClass, SomeClass.Options) -> ()
   // CHECK: [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+  // CHECK: [[APPLY_FN:%[0-9]+]] = function_ref @IAMSomeClassApplyOptions : $@convention(c) (SomeClass, SomeClass.Options) -> ()
   // CHECK: apply [[APPLY_FN]]([[BORROWED_OBJ]], [[OPTS]])
   // CHECK: end_borrow [[BORROWED_OBJ]] from [[OBJ]]
   // CHECK: destroy_value [[OBJ]]
diff --git a/test/SILGen/init_ref_delegation.swift b/test/SILGen/init_ref_delegation.swift
index 1059dd2..758a58c 100644
--- a/test/SILGen/init_ref_delegation.swift
+++ b/test/SILGen/init_ref_delegation.swift
@@ -10,11 +10,11 @@
     // CHECK-NEXT:   [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S }
     // CHECK-NEXT:   [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
     // CHECK-NEXT:   [[PB:%.*]] = project_box [[MARKED_SELF_BOX]]
-    // CHECK:   [[S_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin S.Type) -> S
     
-    // CHECK:   [[X_CTOR:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK-NEXT:   [[X_META:%[0-9]+]] = metatype $@thin X.Type
+    // CHECK:   [[X_CTOR:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK-NEXT:   [[X:%[0-9]+]] = apply [[X_CTOR]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+    // CHECK:   [[S_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin S.Type) -> S
     // CHECK-NEXT:   [[REPLACEMENT_SELF:%[0-9]+]] = apply [[S_DELEG_INIT]]([[X]], [[SELF_META]]) : $@convention(method) (X, @thin S.Type) -> S
     self.init(x: X())
     // CHECK-NEXT:   assign [[REPLACEMENT_SELF]] to [[PB]] : $*S
@@ -38,11 +38,10 @@
     // CHECK:   [[MARKED_E_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[E_BOX]]
     // CHECK:   [[PB:%.*]] = project_box [[MARKED_E_BOX]]
 
-    // CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1EO{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin E.Type) -> E
-
-    // CHECK:   [[E_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK:   [[X_META:%[0-9]+]] = metatype $@thin X.Type
+    // CHECK:   [[E_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK:   [[X:%[0-9]+]] = apply [[E_DELEG_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+    // CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1EO{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin E.Type) -> E
     // CHECK:   [[S:%[0-9]+]] = apply [[X_INIT]]([[X]], [[E_META]]) : $@convention(method) (X, @thin E.Type) -> E
     // CHECK:   assign [[S:%[0-9]+]] to [[PB]] : $*E
     // CHECK:   [[E_BOX1:%[0-9]+]] = load [trivial] [[PB]] : $*E
@@ -62,13 +61,13 @@
     // CHECK:   [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S2 }
     // CHECK:   [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
     // CHECK:   [[PB:%.*]] = project_box [[MARKED_SELF_BOX]]
-    // CHECK:   [[S2_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation2S2V{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
 
-    // CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK:   [[X_META:%[0-9]+]] = metatype $@thin X.Type
+    // CHECK:   [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
     // CHECK:   [[X:%[0-9]+]] = apply [[X_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
     // CHECK:   [[X_BOX:%[0-9]+]] = alloc_stack $X
     // CHECK:   store [[X]] to [trivial] [[X_BOX]] : $*X
+    // CHECK:   [[S2_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation2S2V{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
     // CHECK:   [[SELF_BOX1:%[0-9]+]] = apply [[S2_DELEG_INIT]]<X>([[X_BOX]], [[S2_META]]) : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
     // CHECK:   dealloc_stack [[X_BOX]] : $*X
     // CHECK:   assign [[SELF_BOX1]] to [[PB]] : $*S2
@@ -95,8 +94,7 @@
 
     // CHECK:   store [[ORIG_SELF]] to [init] [[PB]] : $*C1
     // CHECK:   [[SELF_FROM_BOX:%[0-9]+]] = load [take] [[PB]] : $*C1
-    // CHECK:   [[BORROWED_SELF_FROM_BOX:%.*]] = begin_borrow [[SELF_FROM_BOX]]
-    // CHECK:   [[DELEG_INIT:%[0-9]+]] = class_method [[BORROWED_SELF_FROM_BOX]] : $C1, #C1.init!initializer.1 : (C1.Type) -> (X, X) -> C1, $@convention(method) (X, X, @owned C1) -> @owned C1
+    // CHECK:   [[DELEG_INIT:%[0-9]+]] = class_method [[SELF_FROM_BOX]] : $C1, #C1.init!initializer.1 : (C1.Type) -> (X, X) -> C1, $@convention(method) (X, X, @owned C1) -> @owned C1
     // CHECK:   [[SELFP:%[0-9]+]] = apply [[DELEG_INIT]]([[X]], [[X]], [[SELF_FROM_BOX]]) : $@convention(method) (X, X, @owned C1) -> @owned C1
     // CHECK:   store [[SELFP]] to [init] [[PB]] : $*C1
     // CHECK:   [[SELFP:%[0-9]+]] = load [copy] [[PB]] : $*C1
@@ -119,8 +117,7 @@
     // CHECK:   [[PB_SELF:%.*]] = project_box [[MARKED_SELF_BOX]]
     // CHECK:   store [[ORIG_SELF]] to [init] [[PB_SELF]] : $*C2
     // CHECK:   [[SELF:%[0-9]+]] = load [take] [[PB_SELF]] : $*C2
-    // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-    // CHECK:   [[DELEG_INIT:%[0-9]+]] = class_method [[BORROWED_SELF]] : $C2, #C2.init!initializer.1 : (C2.Type) -> (X, X) -> C2, $@convention(method) (X, X, @owned C2) -> @owned C2
+    // CHECK:   [[DELEG_INIT:%[0-9]+]] = class_method [[SELF]] : $C2, #C2.init!initializer.1 : (C2.Type) -> (X, X) -> C2, $@convention(method) (X, X, @owned C2) -> @owned C2
     // CHECK:   [[REPLACE_SELF:%[0-9]+]] = apply [[DELEG_INIT]]([[X]], [[X]], [[SELF]]) : $@convention(method) (X, X, @owned C2) -> @owned C2
     // CHECK:   store [[REPLACE_SELF]] to [init] [[PB_SELF]] : $*C2
     // CHECK:   [[VAR_15:%[0-9]+]] = load [copy] [[PB_SELF]] : $*C2
diff --git a/test/SILGen/initializers.swift b/test/SILGen/initializers.swift
index e438fc8..44a1999 100644
--- a/test/SILGen/initializers.swift
+++ b/test/SILGen/initializers.swift
@@ -644,13 +644,13 @@
   // Now we begin argument emission where we perform the unwrap.
   // CHECK:   [[SELF:%.*]] = load [take] [[PROJ]]
   // CHECK:   [[BASE_SELF:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass
-  // CHECK:   [[INIT_FN:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method)
   // CHECK:   [[UNWRAP_FN:%.*]] = function_ref @_T021failable_initializers6unwrapS2iKF : $@convention(thin)
   // CHECK:   try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
   //
   // Now we emit the call to the initializer. Notice how we return self back to
   // its memory locatio nbefore any other work is done.
   // CHECK: [[NORMAL_BB]](
+  // CHECK:   [[INIT_FN:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method)
   // CHECK:   [[BASE_SELF_INIT:%.*]] = apply [[INIT_FN]]({{%.*}}, [[BASE_SELF]])
   // CHECK:   [[SELF:%.*]] = unchecked_ref_cast [[BASE_SELF_INIT]] : $ThrowBaseClass to $ThrowDerivedClass
   // CHECK:   store [[SELF]] to [init] [[PROJ]]
@@ -755,12 +755,12 @@
   // CHECK: [[UNWRAP_NORMAL_BB]](
   // CHECK:   [[SELF:%.*]] = load [take] [[PROJ]]
   // CHECK:   [[SELF_CAST:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass
-  // CHECK:   [[INIT_FN2:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
   // CHECK:   [[UNWRAP_FN2:%.*]] = function_ref @_T021failable_initializers6unwrapS2iKF : $@convention(thin) (Int) -> (Int, @error Error)
   // CHECK:   try_apply [[UNWRAP_FN2]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[UNWRAP_NORMAL_BB2:bb[0-9]+]], error [[UNWRAP_ERROR_BB2:bb[0-9]+]]
   //
   // Then since this example has a
   // CHECK: [[UNWRAP_NORMAL_BB2]]([[INT:%.*]] : @trivial $Int):
+  // CHECK:   [[INIT_FN2:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
   // CHECK:   [[NEW_SELF_CAST:%.*]] = apply [[INIT_FN2]]([[INT]], [[SELF_CAST]]) : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
   // CHECK:   [[NEW_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF_CAST]] : $ThrowBaseClass to $ThrowDerivedClass
   // CHECK:   store [[NEW_SELF]] to [init] [[PROJ]]
diff --git a/test/SILGen/let_decls.swift b/test/SILGen/let_decls.swift
index 46c5b64..8b75efd 100644
--- a/test/SILGen/let_decls.swift
+++ b/test/SILGen/let_decls.swift
@@ -73,9 +73,9 @@
   
   // CHECK-NOT: destroy_value
 
-  // CHECK: [[USEFN:%[0-9]+]] = function_ref{{.*}}useAString
-  // CHECK-NEXT: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+  // CHECK: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
   // CHECK-NEXT: [[STR_COPY:%.*]] = copy_value [[BORROWED_STR]]
+  // CHECK: [[USEFN:%[0-9]+]] = function_ref{{.*}}useAString
   // CHECK-NEXT: [[USE:%[0-9]+]] = apply [[USEFN]]([[STR_COPY]])
   // CHECK-NEXT: end_borrow [[BORROWED_STR]] from [[STR]]
   useAString(o)
@@ -98,10 +98,10 @@
 func testAddressOnlyStructString<T>(_ a : T) -> String {
   return produceAddressOnlyStruct(a).str
   
-  // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
   // CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
   // CHECK: [[ARG:%.*]] = alloc_stack $T
   // CHECK: copy_addr [[FUNC_ARG]] to [initialization] [[ARG]]
+  // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
   // CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[ARG]])
   // CHECK-NEXT: dealloc_stack [[ARG]]
   // CHECK-NEXT: [[STRADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.str
@@ -115,9 +115,9 @@
 func testAddressOnlyStructElt<T>(_ a : T) -> T {
   return produceAddressOnlyStruct(a).elt
   
-  // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
   // CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
   // CHECK: [[ARG:%.*]] = alloc_stack $T
+  // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
   // CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[ARG]])
   // CHECK-NEXT: dealloc_stack [[ARG]]
   // CHECK-NEXT: [[ELTADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.elt
diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift
index dfe57aa..8f13ad0 100644
--- a/test/SILGen/lifetime.swift
+++ b/test/SILGen/lifetime.swift
@@ -172,9 +172,9 @@
 // CHECK-LABEL: sil hidden @_T08lifetime16reftype_call_argyyF
 func reftype_call_arg() {
     reftype_func_with_arg(reftype_func())
-    // CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
     // CHECK: [[RF:%[0-9]+]] = function_ref @_T08lifetime12reftype_func{{[_0-9a-zA-Z]*}}F
     // CHECK: [[R1:%[0-9]+]] = apply [[RF]]
+    // CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
     // CHECK: [[R2:%[0-9]+]] = apply [[RFWA]]([[R1]])
     // CHECK: destroy_value [[R2]]
     // CHECK: return
@@ -188,9 +188,9 @@
 // CHECK:   [[A1_COPY:%.*]] = copy_value [[BORROWED_A1]]
 // CHECK:   store [[A1_COPY]] to [init] [[PB]]
 // CHECK:   end_borrow [[BORROWED_A1]] from [[A1]]
-// CHECK:   [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
 // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
 // CHECK:   [[A2:%[0-9]+]] = load [copy] [[READ]]
+// CHECK:   [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
 // CHECK:   [[RESULT:%.*]] = apply [[RFWA]]([[A2]])
 // CHECK:   destroy_value [[RESULT]]
 // CHECK:   destroy_value [[AADDR]]
@@ -343,9 +343,9 @@
 // CHECK-LABEL: sil hidden @_T08lifetime28struct_with_ref_materializedyyF
 func struct_with_ref_materialized() {
   fragile_struct_with_ref_elements().gimel()
-  // CHECK: [[METHOD:%[0-9]+]] = function_ref @_T08lifetime4BethV5gimel{{[_0-9a-zA-Z]*}}F
   // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T08lifetime32fragile_struct_with_ref_elementsAA4BethVyF
   // CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]
+  // CHECK: [[METHOD:%[0-9]+]] = function_ref @_T08lifetime4BethV5gimel{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[METHOD]]([[STRUCT]])
 }
 
@@ -744,9 +744,9 @@
     super.init(y: y)
     // CHECK: [[THIS1:%[0-9]+]] = load [take] [[PB_BOX]]
     // CHECK: [[THIS1_SUP:%[0-9]+]] = upcast [[THIS1]] : ${{.*}} to $B
-    // CHECK: [[SUPER_CTOR:%[0-9]+]] = function_ref @_T08lifetime1BCACSi1y_tcfc : $@convention(method) (Int, @owned B) -> @owned B
     // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PY]]
     // CHECK: [[Y:%[0-9]+]] = load [trivial] [[READ]]
+    // CHECK: [[SUPER_CTOR:%[0-9]+]] = function_ref @_T08lifetime1BCACSi1y_tcfc : $@convention(method) (Int, @owned B) -> @owned B
     // CHECK: [[THIS2_SUP:%[0-9]+]] = apply [[SUPER_CTOR]]([[Y]], [[THIS1_SUP]])
     // CHECK: [[THIS2:%[0-9]+]] = unchecked_ref_cast [[THIS2_SUP]] : $B to $D
     // CHECK: [[THIS1:%[0-9]+]] = load [copy] [[PB_BOX]]
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index 99232f0..80f2426 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -364,23 +364,21 @@
   improve(&wizard.hocus)
 }
 // CHECK-LABEL: sil hidden @_T017materializeForSet13improveWizardyAA0E0VzF
-// CHECK:       [[IMPROVE:%.*]] = function_ref @_T017materializeForSet7improveySizF :
-// CHECK-NEXT:  [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Wizard
+// CHECK:       [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Wizard
 // CHECK-NEXT:  [[TEMP:%.*]] = alloc_stack $Int
 //   Call the getter and materialize the result in the temporary.
 // CHECK-NEXT:  [[T0:%.*]] = load [trivial] [[WRITE:.*]] : $*Wizard
-// CHECK-NEXT:  function_ref
-// CHECK-NEXT:  [[GETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivg
-// CHECK-NEXT:  [[WTEMP:%.*]] = alloc_stack $Wizard
+// CHECK:       [[WTEMP:%.*]] = alloc_stack $Wizard
 // CHECK-NEXT:  store [[T0]] to [trivial] [[WTEMP]]
+// CHECK:       [[GETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivg
 // CHECK-NEXT:  [[T0:%.*]] = apply [[GETTER]]<Wizard>([[WTEMP]])
 // CHECK-NEXT:  dealloc_stack [[WTEMP]]
 // CHECK-NEXT:  store [[T0]] to [trivial] [[TEMP]]
 //   Call improve.
+// CHECK:       [[IMPROVE:%.*]] = function_ref @_T017materializeForSet7improveySizF :
 // CHECK-NEXT:  apply [[IMPROVE]]([[TEMP]])
 // CHECK-NEXT:  [[T0:%.*]] = load [trivial] [[TEMP]]
-// CHECK-NEXT:  function_ref
-// CHECK-NEXT:  [[SETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivs
+// CHECK:       [[SETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivs
 // CHECK-NEXT:  apply [[SETTER]]<Wizard>([[T0]], [[WRITE]])
 // CHECK-NEXT:  end_access [[WRITE]] : $*Wizard
 // CHECK-NEXT:  dealloc_stack [[TEMP]]
@@ -574,10 +572,10 @@
 
   // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIexir_A2CIexyd_TR : $@convention(thin) (TuxedoPanda, @owned @callee_owned (@in TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
 
-  // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcvs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
-
   // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIexyd_A2CIexir_TR : $@convention(thin) (@in TuxedoPanda, @owned @callee_owned (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
 
+  // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcvs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
+
 // CHECK: }
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T017materializeForSet11TuxedoPandaVAA0E0A2aDP1xxxcvmTW
diff --git a/test/SILGen/metatypes.swift b/test/SILGen/metatypes.swift
index 8f9b41f..36b2588 100644
--- a/test/SILGen/metatypes.swift
+++ b/test/SILGen/metatypes.swift
@@ -89,8 +89,8 @@
 }
 
 // CHECK-LABEL: sil hidden @_T09metatypes36existential_metatype_from_thin_valueypXpyF : $@convention(thin) () -> @thick Any.Type
+// CHECK:      [[T1:%.*]] = metatype $@thin SomeStruct.Type
 // CHECK:      [[T0:%.*]] = function_ref @_T09metatypes10SomeStructV{{[_0-9a-zA-Z]*}}fC
-// CHECK-NEXT: [[T1:%.*]] = metatype $@thin SomeStruct.Type
 // CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
 // CHECK-NEXT: debug_value [[T2]] : $SomeStruct, let, name "s"
 // CHECK-NEXT: [[T0:%.*]] = metatype $@thin SomeStruct.Type
diff --git a/test/SILGen/objc_attr_NSManaged.swift b/test/SILGen/objc_attr_NSManaged.swift
index 7d4553a..c264d2b 100644
--- a/test/SILGen/objc_attr_NSManaged.swift
+++ b/test/SILGen/objc_attr_NSManaged.swift
@@ -23,10 +23,10 @@
   // Make sure that we're calling through the @objc entry points.
   // CHECK-LABEL: sil hidden @_T019objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed SwiftGizmo) -> () {
   func modifyX() {
-    // CHECK:   [[SETTER:%[0-9]+]] = objc_method [[SELF:%.*]] : $SwiftGizmo, #SwiftGizmo.x!setter.1.foreign : (SwiftGizmo) -> (X) -> (), $@convention(objc_method) (X, SwiftGizmo) -> ()
-    // CHECK:   [[GETTER:%[0-9]+]] = objc_method [[SELF]] : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : (SwiftGizmo) -> () -> X, $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+    // CHECK:   [[GETTER:%[0-9]+]] = objc_method [[SELF:%.*]] : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : (SwiftGizmo) -> () -> X, $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
     // CHECK-NEXT: apply [[GETTER]]([[SELF]]) : $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
     // CHECK-NOT: return
+    // CHECK:   [[SETTER:%[0-9]+]] = objc_method [[SELF]] : $SwiftGizmo, #SwiftGizmo.x!setter.1.foreign : (SwiftGizmo) -> (X) -> (), $@convention(objc_method) (X, SwiftGizmo) -> ()
     // CHECK:  apply [[SETTER]]([[XMOD:%.*]], [[SELF]]) : $@convention(objc_method) (X, SwiftGizmo) -> ()
     x = x.foo()
     // CHECK: return
diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index 89d3551..08b07c3 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -101,7 +101,6 @@
 ) -> (Int, String, String?, String?) {
   // CHECK: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @owned $@callee_owned (Int) -> Int, [[ARG2:%.*]] : @owned $@callee_owned (@owned String) -> @owned String, [[ARG3:%.*]] : @owned $@callee_owned (@owned Optional<String>) -> @owned Optional<String>):
   // CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-  // CHECK: [[FOO:%.*]] =  objc_method [[BORROWED_ARG0]] : $Foo, #Foo.foo!1.foreign
   // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
   // CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
   // CHECK: [[CONVERT:%.*]] = convert_function [[CLOSURE_COPY]]
@@ -111,20 +110,21 @@
   // CHECK: [[F_BLOCK_INVOKE:%.*]] = function_ref @_T0S2iIxyd_S2iIyByd_TR
   // CHECK: [[F_STACK_BLOCK:%.*]] = init_block_storage_header [[F_BLOCK_STORAGE]] : {{.*}}, invoke [[F_BLOCK_INVOKE]]
   // CHECK: [[F_BLOCK:%.*]] = copy_block [[F_STACK_BLOCK]]
+  // CHECK: [[FOO:%.*]] =  objc_method [[BORROWED_ARG0]] : $Foo, #Foo.foo!1.foreign
   // CHECK: apply [[FOO]]([[F_BLOCK]]
 
   // CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-  // CHECK: [[BAR:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bar!1.foreign
   // CHECK: [[G_BLOCK_INVOKE:%.*]] = function_ref @_T0S2SIxxo_So8NSStringCABIyBya_TR
   // CHECK: [[G_STACK_BLOCK:%.*]] = init_block_storage_header {{.*}}, invoke [[G_BLOCK_INVOKE]]
   // CHECK: [[G_BLOCK:%.*]] = copy_block [[G_STACK_BLOCK]]
+  // CHECK: [[BAR:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bar!1.foreign
   // CHECK: apply [[BAR]]([[G_BLOCK]]
 
   // CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-  // CHECK: [[BAS:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bas!1.foreign
   // CHECK: [[H_BLOCK_INVOKE:%.*]] = function_ref @_T0SSSgAAIxxo_So8NSStringCSgADIyBya_TR
   // CHECK: [[H_STACK_BLOCK:%.*]] = init_block_storage_header {{.*}}, invoke [[H_BLOCK_INVOKE]]
   // CHECK: [[H_BLOCK:%.*]] = copy_block [[H_STACK_BLOCK]]
+  // CHECK: [[BAS:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bas!1.foreign
   // CHECK: apply [[BAS]]([[H_BLOCK]]
 
   // CHECK: [[G_BLOCK:%.*]] = copy_block {{%.*}} : $@convention(block) (NSString) -> @autoreleased NSString
@@ -188,3 +188,11 @@
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ix_Ixx_IyB_IyBy_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_owned (@owned @noescape @callee_owned () -> ()) -> (), @convention(block) @noescape () -> ()) -> ()
 // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0IyB_Ix_TR : $@convention(thin) (@owned @convention(block) @noescape () -> ()) -> ()
 
+// rdar://35402696
+func takeOptStringFunction(fn: (String) -> String?) {}
+func testGlobalBlock() {
+  takeOptStringFunction(fn: GlobalBlock)
+}
+// CHECK-LABEL: sil hidden @_T020objc_blocks_bridging15testGlobalBlockyyF
+// CHECK: global_addr @GlobalBlock : $*@convention(block) (NSString) -> @autoreleased Optional<NSString>
+// CHECK: function_ref @_T0So8NSStringCABSgIeyBya_S2SIexxo_TR : $@convention(thin) (@owned String, @owned @convention(block) (NSString) -> @autoreleased Optional<NSString>) -> @owned String
diff --git a/test/SILGen/objc_bridged_results.swift b/test/SILGen/objc_bridged_results.swift
index da859c8..d83c0c5 100644
--- a/test/SILGen/objc_bridged_results.swift
+++ b/test/SILGen/objc_bridged_results.swift
@@ -125,10 +125,9 @@
 
 // CHECK-LABEL: sil hidden @_T020objc_bridged_results13testClassPropSSyF
 func testClassProp() -> String {
-  // CHECK: [[CLASS:%.+]] = metatype $@thick Test.Type
-  // CHECK: [[METHOD:%.+]] = objc_method [[CLASS]] : $@thick Test.Type, #Test.nonnullSharedString!getter.1.foreign : (Test.Type) -> () -> String, $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
-  // CHECK: [[OBJC_CLASS:%.+]] = thick_to_objc_metatype [[CLASS]] : $@thick Test.Type to $@objc_metatype Test.Type
-  // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[OBJC_CLASS]]) : $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
+  // CHECK: [[CLASS:%.+]] = metatype $@objc_metatype Test.Type
+  // CHECK: [[METHOD:%.+]] = objc_method [[CLASS]] : $@objc_metatype Test.Type, #Test.nonnullSharedString!getter.1.foreign : (Test.Type) -> () -> String, $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
+  // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[CLASS]]) : $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
   // CHECK: [[CONVERT:%[0-9]+]] = function_ref @_T0SS10FoundationE36_unconditionallyBridgeFromObjectiveCSSSo8NSStringCSgFZ
   // CHECK: [[STRING_META:%[0-9]+]] = metatype $@thin String.Type
   // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]([[COCOA_VAL]], [[STRING_META]]) : $@convention(method) (@owned Optional<NSString>, @thin String.Type) -> @owned String
diff --git a/test/SILGen/objc_bridging.swift b/test/SILGen/objc_bridging.swift
index 7aef8ed..644e1ad 100644
--- a/test/SILGen/objc_bridging.swift
+++ b/test/SILGen/objc_bridging.swift
@@ -87,12 +87,12 @@
 // CHECK-LABEL: sil hidden @_T013objc_bridging6setFoo{{.*}}F
 // CHECK: bb0([[ARG0:%.*]] : @owned $Foo, {{%.*}} : @owned $String):
 // CHECK:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK:   [[SET_FOO:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setFoo!1.foreign
 // CHECK:   [[NATIVE:%.*]] = load
 // CHECK:   [[STRING_TO_NSSTRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
 // CHECK:   [[BORROWED_NATIVE:%.*]] = begin_borrow [[NATIVE]]
 // CHECK:   [[BRIDGED:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_NATIVE]])
 // CHECK:   [[OPT_BRIDGED:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK:   [[SET_FOO:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setFoo!1.foreign
 // CHECK:   apply [[SET_FOO]]([[OPT_BRIDGED]], [[BORROWED_ARG0]]) : $@convention(objc_method) (Optional<NSString>, Foo) -> ()
 // CHECK:   destroy_value [[OPT_BRIDGED]]
 // CHECK:   end_borrow [[BORROWED_ARG0]] from [[ARG0]]
@@ -109,9 +109,9 @@
 // CHECK-ios-i386:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
 // CHECK-ios-i386:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Bool
 // CHECK-ios-i386:   [[OBJC_BOOL:%.*]] = apply [[METHOD]]([[BORROWED_SELF]])  : $@convention(objc_method) (Foo) -> ObjCBool
+// CHECK-ios-i386:   end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK-ios-i386:   [[CONVERT:%.*]] = function_ref @swift_ObjCBoolToBool : $@convention(thin) (ObjCBool) -> Bool
 // CHECK-ios-i386:   [[SWIFT_BOOL:%.*]] = apply [[CONVERT]]([[OBJC_BOOL]]) : $@convention(thin) (ObjCBool) -> Bool
-// CHECK-ios-i386:   end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK-ios-i386:   return [[SWIFT_BOOL]] : $Bool
 // CHECK-ios-i386: }
 
@@ -129,9 +129,9 @@
 // CHECK-macosx-x86_64:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
 // CHECK-macosx-x86_64:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Bool
 // CHECK-macosx-x86_64:   [[OBJC_BOOL:%.*]] = apply [[METHOD]]([[BORROWED_SELF]])  : $@convention(objc_method) (Foo) -> ObjCBool
+// CHECK-macosx-x86_64:   end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK-macosx-x86_64:   [[CONVERT:%.*]] = function_ref @swift_ObjCBoolToBool : $@convention(thin) (ObjCBool) -> Bool
 // CHECK-macosx-x86_64:   [[SWIFT_BOOL:%.*]] = apply [[CONVERT]]([[OBJC_BOOL]]) : $@convention(thin) (ObjCBool) -> Bool
-// CHECK-macosx-x86_64:   end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK-macosx-x86_64:   return [[SWIFT_BOOL]] : $Bool
 // CHECK-macosx-x86_64: }
 
@@ -160,9 +160,9 @@
 // CHECK-ios-i386-LABEL: sil hidden @_T013objc_bridging6setZim{{.*}}F
 // CHECK-ios-i386: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @trivial $Bool):
 // CHECK-ios-i386:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK-ios-i386:   [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
 // CHECK-ios-i386:   [[CONVERT:%.*]] = function_ref @swift_BoolToObjCBool : $@convention(thin) (Bool) -> ObjCBool
 // CHECK-ios-i386:   [[OBJC_BOOL:%.*]] = apply [[CONVERT]]([[ARG1]]) : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-ios-i386:   [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
 // CHECK-ios-i386:   apply [[METHOD]]([[OBJC_BOOL]], [[BORROWED_ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
 // CHECK-ios-i386:   end_borrow [[BORROWED_ARG0]] from [[ARG0]]
 // CHECK-ios-i386:   destroy_value [[ARG0]]
@@ -171,9 +171,9 @@
 // CHECK-macosx-x86_64-LABEL: sil hidden @_T013objc_bridging6setZim{{.*}}F
 // CHECK-macosx-x86_64: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @trivial $Bool):
 // CHECK-macosx-x86_64:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK-macosx-x86_64:   [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
 // CHECK-macosx-x86_64:   [[CONVERT:%.*]] = function_ref @swift_BoolToObjCBool : $@convention(thin) (Bool) -> ObjCBool
 // CHECK-macosx-x86_64:   [[OBJC_BOOL:%.*]] = apply [[CONVERT]]([[ARG1]]) : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-macosx-x86_64:   [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
 // CHECK-macosx-x86_64:   apply [[METHOD]]([[OBJC_BOOL]], [[BORROWED_ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
 // CHECK-macosx-x86_64:   end_borrow [[BORROWED_ARG0]] from [[ARG0]]
 // CHECK-macosx-x86_64:   destroy_value [[ARG0]]
@@ -258,13 +258,13 @@
 }
 // CHECK-LABEL: sil hidden @_T013objc_bridging10callSetBar{{.*}}F
 // CHECK: bb0({{%.*}} : @owned $String):
-// CHECK:   [[SET_BAR:%.*]] = function_ref @setBar
 // CHECK:   [[NATIVE:%.*]] = load
 // CHECK:   [[STRING_TO_NSSTRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
 // CHECK:   [[BORROWED_NATIVE:%.*]] = begin_borrow [[NATIVE]]
 // CHECK:   [[BRIDGED:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_NATIVE]])
 // CHECK:   [[OPT_BRIDGED:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
 // CHECK:   end_borrow [[BORROWED_NATIVE]] from [[NATIVE]]
+// CHECK:   [[SET_BAR:%.*]] = function_ref @setBar
 // CHECK:   apply [[SET_BAR]]([[OPT_BRIDGED]])
 // CHECK:   destroy_value [[OPT_BRIDGED]]
 // CHECK: }
@@ -660,13 +660,13 @@
 
 // CHECK-LABEL: sil hidden @_T013objc_bridging15castToCFunctionySV3ptr_tF : $@convention(thin) (UnsafeRawPointer) -> () {
 func castToCFunction(ptr: UnsafeRawPointer) {
-  // CHECK: [[CASTFN:%.*]] = function_ref @_T0s13unsafeBitCastq_x_q_m2totr0_lF
   // CHECK: [[OUT:%.*]] = alloc_stack $@convention(c) (Optional<AnyObject>) -> ()
   // CHECK: [[IN:%.]] = alloc_stack $UnsafeRawPointer
   // CHECK: store %0 to [trivial] [[IN]] : $*UnsafeRawPointer
   // CHECK: [[META:%.*]] = metatype $@thick (@convention(c) (Optional<AnyObject>) -> ()).Type
+  // CHECK: [[CASTFN:%.*]] = function_ref @_T0s13unsafeBitCastq_x_q_m2totr0_lF
   // CHECK: apply [[CASTFN]]<UnsafeRawPointer, @convention(c) (AnyObject?) -> ()>([[OUT]], [[IN]], [[META]]) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @thick τ_0_1.Type) -> @out τ_0_1
-  // CHECK: [[RESULT:%.*]] = load [trivial] %3 : $*@convention(c) (Optional<AnyObject>) -> ()
+  // CHECK: [[RESULT:%.*]] = load [trivial] [[OUT]] : $*@convention(c) (Optional<AnyObject>) -> ()
   typealias Fn = @convention(c) (AnyObject?) -> Void
   unsafeBitCast(ptr, to: Fn.self)(nil)
 }
diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index d32606b..4b1006a 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -40,7 +40,6 @@
   // CHECK:   debug_value_addr [[OPT_ANY:%.*]] : $*Optional<Any>
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK:   [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]]
   // CHECK:   [[STRING_COPY:%.*]] = copy_value [[BORROWED_STRING]]
   // CHECK:   [[BRIDGE_STRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
@@ -50,50 +49,51 @@
   // CHECK:   end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
   // CHECK:   destroy_value [[STRING_COPY]]
   // CHECK:   end_borrow [[BORROWED_STRING]] from [[STRING]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(string)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_NSSTRING:%.*]] = begin_borrow [[NSSTRING]]
   // CHECK:   [[NSSTRING_COPY:%.*]] = copy_value [[BORROWED_NSSTRING]]
   // CHECK:   [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
   // CHECK:   end_borrow [[BORROWED_NSSTRING]] from [[NSSTRING]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(nsString)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_CLASS_GENERIC:%.*]] = begin_borrow [[CLASS_GENERIC]]
   // CHECK:   [[CLASS_GENERIC_COPY:%.*]] = copy_value [[BORROWED_CLASS_GENERIC]]
   // CHECK:   [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
   // CHECK:   end_borrow [[BORROWED_CLASS_GENERIC]] from [[CLASS_GENERIC]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(classGeneric)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_OBJECT:%.*]] = begin_borrow [[OBJECT]]
   // CHECK:   [[OBJECT_COPY:%.*]] = copy_value [[BORROWED_OBJECT]]
   // CHECK:   end_borrow [[BORROWED_OBJECT]] from [[OBJECT]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[OBJECT_COPY]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[OBJECT_COPY]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(object)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_CLASS_EXISTENTIAL:%.*]] = begin_borrow [[CLASS_EXISTENTIAL]]
   // CHECK:   [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[BORROWED_CLASS_EXISTENTIAL]]
   // CHECK:   [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
   // CHECK:   [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
   // CHECK:   end_borrow [[BORROWED_CLASS_EXISTENTIAL]] from [[CLASS_EXISTENTIAL]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
@@ -102,20 +102,19 @@
   // These cases perform a universal bridging conversion.
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[COPY:%.*]] = alloc_stack $U
   // CHECK:   copy_addr [[GENERIC]] to [initialization] [[COPY]]
   // CHECK:   // function_ref _bridgeAnythingToObjectiveC
   // CHECK:   [[BRIDGE_ANYTHING:%.*]] = function_ref
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<U>([[COPY]])
   // CHECK:   dealloc_stack [[COPY]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(generic)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[COPY:%.*]] = alloc_stack $P
   // CHECK:   copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]]
   // CHECK:   [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened.*P]],
@@ -127,13 +126,13 @@
   // CHECK:   dealloc_stack [[TMP]]
   // CHECK:   destroy_addr [[COPY]]
   // CHECK:   dealloc_stack [[COPY]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(existential)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
   // CHECK:   [[ERROR_COPY:%.*]] = copy_value [[BORROWED_ERROR]] : $Error
   // CHECK:   [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
@@ -144,13 +143,13 @@
   // CHECK:   dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
   // CHECK:   destroy_value [[ERROR_COPY]] : $Error
   // CHECK:   end_borrow [[BORROWED_ERROR]] from [[ERROR]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[BRIDGED_ERROR]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[BRIDGED_ERROR]] : $AnyObject
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(error)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[COPY:%.*]] = alloc_stack $Any
   // CHECK:   copy_addr [[ANY]] to [initialization] [[COPY]]
   // CHECK:   [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
@@ -161,17 +160,18 @@
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
   // CHECK:   destroy_addr [[COPY]]
   // CHECK:   dealloc_stack [[COPY]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[ANYOBJECT]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(any)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[TMP:%.*]] = alloc_stack $KnownUnbridged
   // CHECK:   store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
   // CHECK:   [[BRIDGE_ANYTHING:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveC{{.*}}F
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(knownUnbridged)
@@ -179,7 +179,6 @@
   // These cases bridge using Optional's _ObjectiveCBridgeable conformance.
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_OPT_STRING:%.*]] = begin_borrow [[OPT_STRING]]
   // CHECK:   [[OPT_STRING_COPY:%.*]] = copy_value [[BORROWED_OPT_STRING]]
   // CHECK:   [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
@@ -188,12 +187,12 @@
   // CHECK:   store_borrow [[BORROWED_OPT_STRING_COPY]] to [[TMP]]
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<String>([[TMP]])
   // CHECK:   end_borrow [[BORROWED_OPT_STRING]] from [[OPT_STRING]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(optionalA)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[BORROWED_OPT_NSSTRING:%.*]] = begin_borrow [[OPT_NSSTRING]]
   // CHECK:   [[OPT_NSSTRING_COPY:%.*]] = copy_value [[BORROWED_OPT_NSSTRING]]
   // CHECK:   [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
@@ -202,16 +201,17 @@
   // CHECK:   store_borrow [[BORROWED_OPT_NSSTRING_COPY]] to [[TMP]]
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<NSString>([[TMP]])
   // CHECK:   end_borrow [[BORROWED_OPT_NSSTRING]] from [[OPT_NSSTRING]]
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(optionalB)
 
   // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   [[TMP:%.*]] = alloc_stack $Optional<Any>
   // CHECK:   copy_addr [[OPT_ANY]] to [initialization] [[TMP]]
   // CHECK:   [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
   // CHECK:   [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<Any>([[TMP]])
+  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK:   apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesId(optionalC)
@@ -287,7 +287,6 @@
   // CHECK: [[OPT_OPT_C:%.*]] : $*Optional<Optional<Any>>
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK: [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]]
   // CHECK: [[STRING_COPY:%.*]] = copy_value [[BORROWED_STRING]]
   // CHECK: [[BRIDGE_STRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
@@ -297,57 +296,57 @@
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
   // CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
   // CHECK: destroy_value [[STRING_COPY]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: destroy_value [[OPT_ANYOBJECT]]
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(string)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[BORROWED_NSSTRING:%.*]] = begin_borrow [[NSSTRING]]
   // CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[BORROWED_NSSTRING]]
   // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
   // CHECK: end_borrow [[BORROWED_NSSTRING]] from [[NSSTRING]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(nsString)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[BORROWED_OBJECT:%.*]] = begin_borrow [[OBJECT]]
   // CHECK: [[OBJECT_COPY:%.*]] = copy_value [[BORROWED_OBJECT]]
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[OBJECT_COPY]]
   // CHECK: end_borrow [[BORROWED_OBJECT]] from [[OBJECT]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(object)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[BORROWED_CLASS_GENERIC:%.*]] = begin_borrow [[CLASS_GENERIC]]
   // CHECK: [[CLASS_GENERIC_COPY:%.*]] = copy_value [[BORROWED_CLASS_GENERIC]]
   // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
   // CHECK: end_borrow [[BORROWED_CLASS_GENERIC]] from [[CLASS_GENERIC]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(classGeneric)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[BORROWED_CLASS_EXISTENTIAL:%.*]] = begin_borrow [[CLASS_EXISTENTIAL]]
   // CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[BORROWED_CLASS_EXISTENTIAL]]
   // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
   // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
   // CHECK: end_borrow [[BORROWED_CLASS_EXISTENTIAL]] from [[CLASS_EXISTENTIAL]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(classExistential)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $U
   // CHECK-NEXT: copy_addr [[GENERIC]] to [initialization] [[COPY]]
   // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
@@ -355,13 +354,13 @@
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<U>([[COPY]])
   // CHECK-NEXT: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
   // CHECK-NEXT: dealloc_stack [[COPY]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
   // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(generic)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $P
   // CHECK-NEXT: copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]]
   // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened.*P]],
@@ -374,13 +373,13 @@
 	// CHECK-NEXT: dealloc_stack [[TMP]]
   // CHECK-NEXT: destroy_addr [[COPY]]
 	// CHECK-NEXT: dealloc_stack [[COPY]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
   // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(existential)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
   // CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[BORROWED_ERROR]] : $Error
   // CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
@@ -392,13 +391,13 @@
   // CHECK-NEXT: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
   // CHECK-NEXT: destroy_value [[ERROR_COPY]] : $Error
   // CHECK-NEXT: end_borrow [[BORROWED_ERROR]] from [[ERROR]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: apply [[METHOD]]([[BRIDGED_ERROR_OPT]], [[BORROWED_SELF]])
   // CHECK-NEXT: destroy_value [[BRIDGED_ERROR_OPT]]
   // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(error)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Any
   // CHECK-NEXT: copy_addr [[ANY]] to [initialization] [[COPY]]
   // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
@@ -411,24 +410,24 @@
   // CHECK-NEXT: dealloc_stack [[TMP]]
   // CHECK-NEXT: destroy_addr [[COPY]]
   // CHECK-NEXT: dealloc_stack [[COPY]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
   // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(any)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: [[TMP:%.*]] = alloc_stack $KnownUnbridged
   // CHECK: store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
   // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveC{{.*}}F
   // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
   // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
   // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
   // CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
   receiver.takesNullableId(knownUnbridged)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK: [[BORROWED_OPT_STRING:%.*]] = begin_borrow [[OPT_STRING]]
   // CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[BORROWED_OPT_STRING]]
   // CHECK: switch_enum [[OPT_STRING_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
@@ -449,6 +448,7 @@
   //
   // CHECK: [[JOIN]]([[PHI:%.*]] : @owned $Optional<AnyObject>):
   // CHECK:   end_borrow [[BORROWED_OPT_STRING]] from [[OPT_STRING]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK:   apply [[METHOD]]([[PHI]], [[BORROWED_SELF]])
   // CHECK:   destroy_value [[PHI]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
@@ -459,9 +459,9 @@
   receiver.takesNullableId(optNSString)
 
   // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK: [[BORROWED_OPT_OBJECT:%.*]] = begin_borrow [[OPT_OBJECT]]
   // CHECK: [[OPT_OBJECT_COPY:%.*]] = copy_value [[BORROWED_OPT_OBJECT]]
+  // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
   // CHECK: apply [[METHOD]]([[OPT_OBJECT_COPY]], [[BORROWED_SELF]])
   receiver.takesNullableId(optObject)
   receiver.takesNullableId(optClassGeneric)
@@ -738,6 +738,16 @@
   }
 }
 
+// CHECK-LABEL: sil hidden @_T017objc_bridging_any33bridgeOptionalFunctionToAnyObjectyXlyycSg2fn_tF : $@convention(thin) (@owned Optional<@callee_owned () -> ()>) -> @owned AnyObject
+// CHECK: [[BRIDGE:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+// CHECK: [[FN:%.*]] = function_ref @_T0Iex_ytytIexir_TR
+// CHECK: partial_apply [[FN]]
+// CHECK: [[SELF:%.*]] = alloc_stack $Optional<@callee_owned (@in ()) -> @out ()>
+// CHECK: apply [[BRIDGE]]<() -> ()>([[SELF]])
+func bridgeOptionalFunctionToAnyObject(fn: (() -> ())?) -> AnyObject {
+  return fn as AnyObject
+}
+
 // CHECK-LABEL: sil_witness_table shared [serialized] GenericOption: Hashable module objc_generics {
 // CHECK-NEXT: base_protocol Equatable: GenericOption: Equatable module objc_generics
 // CHECK-NEXT: method #Hashable.hashValue!getter.1: {{.*}} : @_T0SC13GenericOptionVs8Hashable13objc_genericssACP9hashValueSivgTW
diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift
index 6697bd3..e8b23e2 100644
--- a/test/SILGen/objc_bridging_peephole.swift
+++ b/test/SILGen/objc_bridging_peephole.swift
@@ -17,55 +17,55 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole16testMethodResultySo10DummyClassC5dummy_tF
 func testMethodResult(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   useOptNS(dummy.fetchNullableString() as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   useOptNS(dummy.fetchNullproneString() as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+  // CHECK-NEXT: apply [[USE]]([[RESULT]])
   useOptNS(dummy.fetchNonnullString() as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
-  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   useOptAnyObject(dummy.fetchNullableString() as AnyObject?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
-  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   useOptAnyObject(dummy.fetchNullproneString() as AnyObject?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
-  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
-  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+  // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   useOptAnyObject(dummy.fetchNonnullString() as AnyObject?)
 
   // CHECK:      return
@@ -73,29 +73,29 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonNullMethodResultySo10DummyClassC5dummy_tF
 func testNonNullMethodResult(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb1:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb2([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
-  // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.fetchNonnullString() as NSString)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb3:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
-  // CHECK-NEXT: end_borrow [[SELF]] from %0
   useAnyObject(dummy.fetchNonnullString() as AnyObject)
 
   // CHECK:      return
@@ -103,29 +103,29 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole22testForcedMethodResultySo10DummyClassC5dummy_tF
 func testForcedMethodResult(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb1:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb2([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
-  // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.fetchNullproneString() as NSString)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK-NEXT: end_borrow [[SELF]] from %0
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb3:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
-  // CHECK-NEXT: end_borrow [[SELF]] from %0
   useAnyObject(dummy.fetchNullproneString() as AnyObject)
 
   // CHECK:      return
@@ -135,53 +135,53 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole17testPropertyValueySo10DummyClassC5dummy_tF
 func testPropertyValue(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptNS(dummy.nullableStringProperty as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptNS(dummy.nullproneStringProperty as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptNS(dummy.nonnullStringProperty as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptAnyObject(dummy.nullableStringProperty as AnyObject?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptAnyObject(dummy.nullproneStringProperty as AnyObject?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useOptAnyObject(dummy.nonnullStringProperty as AnyObject?)
@@ -191,20 +191,19 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNonNullPropertyValueySo10DummyClassC5dummy_tF
 func testNonNullPropertyValue(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb1:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb2([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.nonnullStringProperty as NSString)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: switch_enum [[RESULT]]
@@ -212,6 +211,7 @@
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useAnyObject(dummy.nonnullStringProperty as AnyObject)
@@ -221,19 +221,18 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testForcedPropertyValueySo10DummyClassC5dummy_tF
 func testForcedPropertyValue(dummy: DummyClass) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:    bb1:
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb2([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.nullproneStringProperty as NSString)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
@@ -242,6 +241,7 @@
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
   // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
   // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useAnyObject(dummy.nullproneStringProperty as AnyObject)
@@ -255,27 +255,27 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonnullSubscriptGetySo0eF0C6object_yXl5indextF
 func testNonnullSubscriptGet(object: NonnullSubscript, index: AnyObject) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
   // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useOptNS(object[index] as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
   // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart
   // CHECK:    bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useNS(object[index] as NSString)
@@ -285,13 +285,13 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptGetySo0eF0C6object_yXl5indextF
 func testNullableSubscriptGet(object: NullableSubscript, index: AnyObject) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
   // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useOptNS(object[index] as NSString?)
@@ -301,27 +301,27 @@
 
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptGetySo0eF0C6object_yXl5indextF
 func testNullproneSubscriptGet(object: NullproneSubscript, index: AnyObject) {
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
-  // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
+  // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
   // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useOptNS(object[index] as NSString?)
 
-  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
   // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
   // CHECK-NEXT: switch_enum [[RESULT]]
   // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart
   // CHECK:    bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   // CHECK:      end_borrow [[SELF]] from %0
   useNS(object[index] as NSString)
@@ -334,32 +334,32 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole18testMethodArgumentySo10DummyClassC5dummy_tF 
 func testMethodArgument(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNonnullString(makeNS() as String)
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullableString(makeNS() as String)
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -371,22 +371,22 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptMethodArgumentySo10DummyClassC5dummy_tF
 func testValueToOptMethodArgument(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullableString(makeNS() as String?)
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -398,20 +398,20 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14MethodArgumentySo10DummyClassC5dummy_tF
 func testOptToOptMethodArgument(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.takeNullableString(makeOptNS() as String?)
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -425,32 +425,32 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole18testPropertySetterySo10DummyClassC5dummy_tF 
 func testPropertySetter(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nonnullStringProperty = makeNS() as String
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullableStringProperty = makeNS() as String
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -462,22 +462,22 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptPropertySetterySo10DummyClassC5dummy_tF
 func testValueToOptPropertySetter(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullableStringProperty = makeNS() as String?
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[OPTARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -489,20 +489,20 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14PropertySetterySo10DummyClassC5dummy_tF
 func testOptToOptPropertySetter(dummy: DummyClass) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   dummy.nullableStringProperty = makeOptNS() as String?
 
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
-  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+  // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
   // CHECK-NEXT: destroy_value [[ARG]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -518,11 +518,11 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonnullSubscriptSetySo0eF0C6object_yXl5indextF
 func testNonnullSubscriptSet(object: NonnullSubscript, index: AnyObject) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[ARG]]
@@ -535,12 +535,12 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptSetySo0eF0C6object_yXl5indextF
 func testNullableSubscriptSet(object: NullableSubscript, index: AnyObject) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[OPTARG]]
@@ -548,12 +548,12 @@
   object[index] = makeNS() as String
 
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[OPTARG]]
@@ -561,11 +561,11 @@
   object[index] = makeNS() as String?
 
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[ARG]]
@@ -578,12 +578,12 @@
 // CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptSetySo0eF0C6object_yXl5indextF 
 func testNullproneSubscriptSet(object: NullproneSubscript, index: AnyObject) {
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[OPTARG]]
@@ -591,12 +591,12 @@
   object[index] = makeNS() as String
 
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[OPTARG]]
@@ -604,11 +604,11 @@
   object[index] = makeNS() as String?
 
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
-  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
   // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
   // CHECK:      [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
   // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+  // CHECK:      [[METHOD:%.*]] = objc_method
   // CHECK:      apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
   // CHECK:      destroy_value [[INDEX]]
   // CHECK:      destroy_value [[ARG]]
diff --git a/test/SILGen/objc_currying.swift b/test/SILGen/objc_currying.swift
index 74c9e38..7818504 100644
--- a/test/SILGen/objc_currying.swift
+++ b/test/SILGen/objc_currying.swift
@@ -13,8 +13,8 @@
 // CHECK-LABEL: sil hidden @_T013objc_currying9curry_podS2icSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
 // CHECK:      bb0([[ARG1:%.*]] : @owned $CurryTest):
 // CHECK:         [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
-// CHECK:         [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:_T0So9CurryTestC3podS2iFTcTO]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
 // CHECK:         [[COPIED_ARG1:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK:         [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:_T0So9CurryTestC3podS2iFTcTO]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
 // CHECK:         [[FN:%.*]] = apply [[THUNK]]([[COPIED_ARG1]])
 // CHECK:         end_borrow [[BORROWED_ARG1]] from [[ARG1]]
 // CHECK:         destroy_value [[ARG1]]
@@ -42,8 +42,8 @@
 // CHECK-LABEL: sil hidden @_T013objc_currying13curry_bridgedSQySSGACcSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (@owned Optional<String>) -> @owned Optional<String>
 // CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest):
 // CHECK:   [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
-// CHECK:   [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:_T0So9CurryTestC7bridgedSQySSGADFTcTO]]
 // CHECK:   [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK:   [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:_T0So9CurryTestC7bridgedSQySSGADFTcTO]]
 // CHECK:   [[FN:%.*]] = apply [[THUNK]]([[ARG1_COPY]])
 // CHECK:   end_borrow [[BORROWED_ARG1]] from [[ARG1]]
 // CHECK:   destroy_value [[ARG1]]
@@ -103,8 +103,8 @@
 // CHECK-LABEL: sil hidden @_T013objc_currying25curry_returnsInnerPointerSQySvGycSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned () -> Optional<UnsafeMutableRawPointer> {
 // CHECK: bb0([[SELF:%.*]] : @owned $CurryTest):
 // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-// CHECK:   [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTcTO]]
 // CHECK:   [[SELF_COPY:%.*]] = copy_value [[BORROWED_SELF]]
+// CHECK:   [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTcTO]]
 // CHECK:   [[FN:%.*]] = apply [[THUNK]]([[SELF_COPY]])
 // CHECK:   end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK:   destroy_value [[SELF]]
diff --git a/test/SILGen/objc_dealloc.swift b/test/SILGen/objc_dealloc.swift
index 3df7cad..e9bcfbf 100644
--- a/test/SILGen/objc_dealloc.swift
+++ b/test/SILGen/objc_dealloc.swift
@@ -12,8 +12,8 @@
   var x = X()
 
   // CHECK-LABEL: sil hidden [transparent] @_T012objc_dealloc10SwiftGizmoC1xAA1XCvpfi : $@convention(thin) () -> @owned X
+  // CHECK:      [[METATYPE:%.*]] = metatype $@thick X.Type
   // CHECK:      [[FN:%.*]] = function_ref @_T012objc_dealloc1XCACycfC : $@convention(method) (@thick X.Type) -> @owned X
-  // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick X.Type
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[METATYPE]]) : $@convention(method) (@thick X.Type) -> @owned X
   // CHECK-NEXT: return [[RESULT]] : $X
 
diff --git a/test/SILGen/objc_extensions.swift b/test/SILGen/objc_extensions.swift
index df804d8..1d5ddfc 100644
--- a/test/SILGen/objc_extensions.swift
+++ b/test/SILGen/objc_extensions.swift
@@ -75,10 +75,6 @@
     // CHECK:   destroy_value [[UPCAST_SELF_COPY]]
     // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
     // CHECK:   [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
-    // CHECK:   [[BORROWED_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF_COPY]] : $Base
-    // CHECK:   [[SUPERREF_DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF]] : $Base to $Sub
-    // CHECK:   [[SET_SUPER_METHOD:%.*]] = objc_super_method [[SUPERREF_DOWNCAST]] : $Sub, #Base.prop!setter.1.foreign : (Base) -> (String!) -> (), $@convention(objc_method) (Optional<NSString>, Base) -> ()
-    // CHECK:    end_borrow [[BORROWED_UPCAST_SELF]]
     // CHECK:   [[BORROWED_NEW_VALUE:%.*]] = begin_borrow [[NEW_VALUE]]
     // CHECK:   [[NEW_VALUE_COPY:%.*]] = copy_value [[BORROWED_NEW_VALUE]]
     // CHECK:   switch_enum [[NEW_VALUE_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
@@ -86,14 +82,17 @@
     // CHECK: bb4([[OLD_STRING:%.*]] : @owned $String):
     // CHECK: bb6([[BRIDGED_NEW_STRING:%.*]] : @owned $Optional<NSString>):
     // CHECK:    end_borrow [[BORROWED_NEW_VALUE]]
+    // CHECK:   [[BORROWED_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF_COPY]] : $Base
+    // CHECK:   [[SUPERREF_DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF]] : $Base to $Sub
+    // CHECK:   [[SET_SUPER_METHOD:%.*]] = objc_super_method [[SUPERREF_DOWNCAST]] : $Sub, #Base.prop!setter.1.foreign : (Base) -> (String!) -> (), $@convention(objc_method) (Optional<NSString>, Base) -> ()
     // CHECK:    apply [[SET_SUPER_METHOD]]([[BRIDGED_NEW_STRING]], [[UPCAST_SELF_COPY]])
     // CHECK:    destroy_value [[BRIDGED_NEW_STRING]]
     // CHECK:    destroy_value [[UPCAST_SELF_COPY]]
-    // CHECK:    [[DIDSET_NOTIFIER:%.*]] = function_ref @_T015objc_extensions3SubC4propSQySSGvW : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> ()
     // CHECK:    [[BORROWED_OLD_NSSTRING_BRIDGED:%.*]] = begin_borrow [[OLD_NSSTRING_BRIDGED]]
     // CHECK:    [[COPIED_OLD_NSSTRING_BRIDGED:%.*]] = copy_value [[BORROWED_OLD_NSSTRING_BRIDGED]]
     // CHECK:    end_borrow [[BORROWED_OLD_NSSTRING_BRIDGED]] from [[OLD_NSSTRING_BRIDGED]]
     // This is an identity cast that should be eliminated by SILGen peepholes.
+    // CHECK:    [[DIDSET_NOTIFIER:%.*]] = function_ref @_T015objc_extensions3SubC4propSQySSGvW : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> ()
     // CHECK:    apply [[DIDSET_NOTIFIER]]([[COPIED_OLD_NSSTRING_BRIDGED]], [[SELF]])
     // CHECK:    destroy_value [[OLD_NSSTRING_BRIDGED]]
     // CHECK:    destroy_value [[NEW_VALUE]]
diff --git a/test/SILGen/objc_factory_init.swift b/test/SILGen/objc_factory_init.swift
index f0e6ed4..8825e70 100644
--- a/test/SILGen/objc_factory_init.swift
+++ b/test/SILGen/objc_factory_init.swift
@@ -30,11 +30,11 @@
   // CHECK:   [[BORROWED_SELF:%.*]] = load_borrow [[PB_BOX]]
   // CHECK:   [[META:%[0-9]+]] = value_metatype $@thick Hive.Type, [[BORROWED_SELF]] : $Hive
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[PB_BOX]]
-  // CHECK:   [[FACTORY:%[0-9]+]] = objc_method [[META]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
   // CHECK:   [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[META]] : $@thick Hive.Type to $@objc_metatype Hive.Type
   // CHECK:   [[BORROWED_QUEEN:%.*]] = begin_borrow [[QUEEN]]
   // CHECK:   [[COPIED_BORROWED_QUEEN:%.*]] = copy_value [[BORROWED_QUEEN]]
   // CHECK:   [[OPT_COPIED_BORROWED_QUEEN:%.*]] = enum $Optional<Bee>, #Optional.some!enumelt.1, [[COPIED_BORROWED_QUEEN]]
+  // CHECK:   [[FACTORY:%[0-9]+]] = objc_method [[OBJC_META]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
   // CHECK:   [[NEW_HIVE:%.*]] = apply [[FACTORY]]([[OPT_COPIED_BORROWED_QUEEN]], [[OBJC_META]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
   // CHECK:   destroy_value [[OPT_COPIED_BORROWED_QUEEN]]
   // CHECK:   end_borrow [[BORROWED_QUEEN]] from [[QUEEN]]
@@ -88,9 +88,9 @@
   // CHECK:   [[UPCAST_BORROWED_SELF:%.*]] = upcast [[BORROWED_SELF]] : $SubHive to $Hive
   // CHECK:   [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST_BORROWED_SELF:%.*]]
   // CHECK:   end_borrow [[BORROWED_SELF]] from [[PB_BOX]]
-  // CHECK:   [[HIVE_INIT_FN:%.*]] = objc_method [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign
   // CHECK:   [[OBJC_METATYPE:%.*]] = thick_to_objc_metatype [[METATYPE]]
   // CHECK:   [[QUEEN:%.*]] = unchecked_ref_cast {{.*}} : $Bee to $Optional<Bee>
+  // CHECK:   [[HIVE_INIT_FN:%.*]] = objc_method [[OBJC_METATYPE]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign
   // CHECK:   apply [[HIVE_INIT_FN]]([[QUEEN]], [[OBJC_METATYPE]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
   // CHECK:   destroy_value [[QUEEN]]
   // CHECK: } // end sil function '_T017objc_factory_init7SubHiveCACyt20delegatesToInherited_tcfc'
diff --git a/test/SILGen/objc_imported_generic.swift b/test/SILGen/objc_imported_generic.swift
index 8029b99..bb6a747 100644
--- a/test/SILGen/objc_imported_generic.swift
+++ b/test/SILGen/objc_imported_generic.swift
@@ -107,8 +107,8 @@
 }
 
 // CHECK-LABEL: sil private @_T021objc_imported_generic0C4FuncyxmRlzClFyycfU_ : $@convention(thin) <V where V : AnyObject> () -> () {
-// CHECK:  [[INIT:%.*]] = function_ref @_T0So12GenericClassCAByxGycfC : $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@thick GenericClass<τ_0_0>.Type) -> @owned GenericClass<τ_0_0>
 // CHECK:  [[META:%.*]] = metatype $@thick GenericClass<V>.Type
+// CHECK:  [[INIT:%.*]] = function_ref @_T0So12GenericClassCAByxGycfC : $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@thick GenericClass<τ_0_0>.Type) -> @owned GenericClass<τ_0_0>
 // CHECK:  apply [[INIT]]<V>([[META]])
 // CHECK:  return
 func genericFunc<V: AnyObject>(_ v: V.Type) {
diff --git a/test/SILGen/objc_init_ref_delegation.swift b/test/SILGen/objc_init_ref_delegation.swift
index 078e725..f397306b2 100644
--- a/test/SILGen/objc_init_ref_delegation.swift
+++ b/test/SILGen/objc_init_ref_delegation.swift
@@ -13,8 +13,7 @@
     // CHECK:   [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
     // CHECK:   store [[ORIG_SELF]] to [init] [[PB_BOX]] : $*Gizmo
     // CHECK:   [[SELF:%[0-9]+]] = load [take] [[PB_BOX]] : $*Gizmo
-    // CHECK:   [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-    // CHECK:   [[INIT_DELEG:%[0-9]+]] = objc_method [[BORROWED_SELF]] : $Gizmo, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+    // CHECK:   [[INIT_DELEG:%[0-9]+]] = objc_method [[SELF]] : $Gizmo, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
     // CHECK:   [[SELF_RET:%[0-9]+]] = apply [[INIT_DELEG]]([[I]], [[SELF]]) : $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
     // CHECK:   [[SELF4:%.*]] = load [copy] [[PB_BOX]]
     // CHECK:   destroy_value [[MARKED_SELF_BOX]]
diff --git a/test/SILGen/objc_ownership_conventions.swift b/test/SILGen/objc_ownership_conventions.swift
index 6b36fa4..d25a82f 100644
--- a/test/SILGen/objc_ownership_conventions.swift
+++ b/test/SILGen/objc_ownership_conventions.swift
@@ -8,8 +8,8 @@
 func test3() -> NSObject {
   // initializer returns at +1
   return Gizmo()
+  // CHECK: [[GIZMO_META:%[0-9]+]] = metatype $@thick Gizmo.Type
   // CHECK: [[CTOR:%[0-9]+]] = function_ref @_T0So5GizmoC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
-  // CHECK-NEXT: [[GIZMO_META:%[0-9]+]] = metatype $@thick Gizmo.Type
   // CHECK-NEXT: [[GIZMO:%[0-9]+]] = apply [[CTOR]]([[GIZMO_META]]) : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
   // CHECK: [[GIZMO_NS:%[0-9]+]] = upcast [[GIZMO:%[0-9]+]] : $Gizmo to $NSObject
   // CHECK: return [[GIZMO_NS]] : $NSObject
@@ -40,13 +40,12 @@
   // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
   // CHECK:   store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
-  // CHECK:   [[CLASS:%.*]] = metatype $@thick Gizmo.Type
-  // CHECK:   [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.inspect!1.foreign
-  // CHECK:   [[OBJC_CLASS:%[0-9]+]] = thick_to_objc_metatype [[CLASS]] : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
+  // CHECK:   [[CLASS:%.*]] = metatype $@objc_metatype Gizmo.Type
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
   // CHECK:   [[V:%.*]] = load [copy] [[READ]]
   // CHECK:   [[G:%.*]] = enum $Optional<Gizmo>, #Optional.some!enumelt.1, [[V]]
-  // CHECK:   apply [[METHOD]]([[G]], [[OBJC_CLASS]])
+  // CHECK:   [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.inspect!1.foreign
+  // CHECK:   apply [[METHOD]]([[G]], [[CLASS]])
   // CHECK:   destroy_value [[G]]
   // CHECK:   destroy_value [[GIZMO_BOX]]
   // CHECK:   destroy_value [[ARG]]
@@ -65,13 +64,12 @@
   // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
   // CHECK:   store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
-  // CHECK:   [[CLASS:%.*]] = metatype $@thick Gizmo.Type
-  // CHECK:   [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.consume!1.foreign
-  // CHECK:   [[OBJC_CLASS:%.*]] = thick_to_objc_metatype [[CLASS]] : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
+  // CHECK:   [[CLASS:%.*]] = metatype $@objc_metatype Gizmo.Type
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
   // CHECK:   [[V:%.*]] = load [copy] [[READ]]
   // CHECK:   [[G:%.*]] = enum $Optional<Gizmo>, #Optional.some!enumelt.1, [[V]]
-  // CHECK:   apply [[METHOD]]([[G]], [[OBJC_CLASS]])
+  // CHECK:   [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.consume!1.foreign
+  // CHECK:   apply [[METHOD]]([[G]], [[CLASS]])
   // CHECK-NOT:  destroy_value [[G]]
   // CHECK:   destroy_value [[GIZMO_BOX]]
   // CHECK-NOT:  destroy_value [[G]]
@@ -94,8 +92,7 @@
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
   // CHECK:   [[G:%.*]] = load [copy] [[READ]]
-  // CHECK:   [[BORROWED_G:%.*]] = begin_borrow [[G]]
-  // CHECK:   [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.fork!1.foreign
+  // CHECK:   [[METHOD:%.*]] = objc_method [[G]] : {{.*}}, #Gizmo.fork!1.foreign
   // CHECK:   apply [[METHOD]]([[G]])
   // CHECK-NOT:  destroy_value [[G]]
   // CHECK:   destroy_value [[GIZMO_BOX]]
@@ -113,10 +110,10 @@
   // CHECK-NOT:  copy_value
   // CHECK:      [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK:      [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.clone!1.foreign
+  // CHECK:      end_borrow [[BORROWED_G]] from [[G]]
   // CHECK-NOT:  copy_value [[RESULT]]
   // CHECK:      bb2([[RESULT:%.*]] : @owned $Gizmo):
   // CHECK-NOT:  copy_value [[RESULT]]
-  // CHECK:      end_borrow [[BORROWED_G]] from [[G]]
   // CHECK-NEXT: destroy_value [[G]]
   // CHECK-NEXT: return [[RESULT]]
 }
@@ -129,10 +126,10 @@
   // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.duplicate!1.foreign
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[BORROWED_G]])
+  // CHECK:      end_borrow [[BORROWED_G]] from [[G]]
   // CHECK-NOT:  copy_value [[RESULT]]
   // CHECK: bb2([[RESULT:%.*]] : @owned $Gizmo):
   // CHECK-NOT:  copy_value [[RESULT]]
-  // CHECK:      end_borrow [[BORROWED_G]] from [[G]]
   // CHECK-NEXT: destroy_value [[G]]
   // CHECK-NEXT: return [[RESULT]]
 }
@@ -143,9 +140,7 @@
   // CHECK:      [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK:      [[G_COPY:%.*]] = copy_value [[BORROWED_G]]
   // CHECK-NEXT: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY]] : $Gizmo to $NSObject
-  // CHECK-NEXT: [[BORROWED_NS_G_COPY:%.*]] = begin_borrow [[NS_G_COPY]]
-  // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[BORROWED_NS_G_COPY]] : $NSObject, #NSObject.classProp!getter.1.foreign : (NSObject) -> () -> AnyObject.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
-  // CHECK-NEXT: end_borrow [[BORROWED_NS_G_COPY]]
+  // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_COPY]] : $NSObject, #NSObject.classProp!getter.1.foreign : (NSObject) -> () -> AnyObject.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
   // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_COPY]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
   // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
   //
@@ -165,9 +160,7 @@
   // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
   // CHECK: [[G_COPY:%.*]] = copy_value [[BORROWED_G]]
   // CHECK: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY:%[0-9]+]] : $Gizmo to $NSObject
-  // CHECK: [[BORROWED_NS_G_COPY:%.*]] = begin_borrow [[NS_G_COPY]]
-  // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[BORROWED_NS_G_COPY]] : $NSObject, #NSObject.qualifiedClassProp!getter.1.foreign : (NSObject) -> () -> NSAnsing.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
-  // CHECK-NEXT: end_borrow [[BORROWED_NS_G_COPY]]
+  // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_COPY]] : $NSObject, #NSObject.qualifiedClassProp!getter.1.foreign : (NSObject) -> () -> NSAnsing.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
   // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_COPY]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
   // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
   //
@@ -215,7 +208,6 @@
 // Handle inner-pointer methods by autoreleasing self after the call.
 // CHECK-LABEL: sil hidden @_T026objc_ownership_conventions18innerPointerMethodySo5GizmoCF : $@convention(thin) (@owned Gizmo) -> () {
 // CHECK: bb0([[ARG:%.*]] : @owned $Gizmo):
-// CHECK:         [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
 // CHECK:         [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:         [[METHOD:%.*]] = objc_method [[BORROWED_ARG]] : $Gizmo, #Gizmo.getBytes!1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
 // CHECK:         [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
@@ -223,6 +215,7 @@
 // it is today though since we are using a reference type.
 // CHECK:         [[PTR:%.*]] = apply [[METHOD]]([[BORROWED_ARG]])
 // CHECK:         autorelease_value [[ARG_COPY]]
+// CHECK:         [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
 // CHECK:         apply [[USE]]([[PTR]])
 // CHECK:         destroy_value [[ARG]]
 func innerPointerMethod(_ g: Gizmo) {
@@ -231,13 +224,13 @@
 
 // CHECK-LABEL: sil hidden @_T026objc_ownership_conventions20innerPointerPropertyySo5GizmoCF : $@convention(thin) (@owned Gizmo) -> () {
 // CHECK:       bb0([[ARG:%.*]] : @owned $Gizmo):
-// CHECK:         [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
 // CHECK:         [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:         [[METHOD:%.*]] = objc_method [[BORROWED_ARG]] : $Gizmo, #Gizmo.innerProperty!getter.1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
 // CHECK:         [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
 // => SEMANTIC ARC TODO: The apply below should be on ARG_COPY. It is benign since objc objects are reference types.
 // CHECK:         [[PTR:%.*]] = apply [[METHOD]]([[BORROWED_ARG]])
 // CHECK:         autorelease_value [[ARG_COPY]]
+// CHECK:         [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
 // CHECK:         apply [[USE]]([[PTR]])
 // CHECK:         destroy_value [[ARG]]
 // CHECK: } // end sil function '_T026objc_ownership_conventions20innerPointerPropertyySo5GizmoCF'
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index 6918532..7a3b8c1 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -27,14 +27,14 @@
 // CHECK-LABEL: sil hidden @_T014objc_protocols0A8_generic{{[_0-9a-zA-Z]*}}F
 // CHECK: bb0([[THIS:%.*]] : @owned $T):
 // -- Result of runce is autoreleased according to default objc conv
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.runce!1.foreign
 // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.runce!1.foreign
 // CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @autoreleased NSObject
 // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
 
 // -- Result of copyRuncing is received copy_valued according to -copy family
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.copyRuncing!1.foreign
 // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.copyRuncing!1.foreign
 // CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @owned NSObject
 // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
 
@@ -47,9 +47,9 @@
 // CHECK-LABEL: sil hidden @_T014objc_protocols0A22_generic_partial_applyyxAA9NSRuncingRzlF : $@convention(thin) <T where T : NSRuncing> (@owned T) -> () {
 func objc_generic_partial_apply<T : NSRuncing>(_ x: T) {
   // CHECK: bb0([[ARG:%.*]] : @owned $T):
-  // CHECK:   [[FN:%.*]] = function_ref @[[THUNK1:_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO]] :
   // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+  // CHECK:   [[FN:%.*]] = function_ref @[[THUNK1:_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO]] :
   // CHECK:   [[METHOD:%.*]] = apply [[FN]]<T>([[ARG_COPY]])
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
   // CHECK:   destroy_value [[METHOD]]
@@ -60,8 +60,8 @@
   // CHECK:   destroy_value [[METHOD]]
   _ = T.runce
 
-  // CHECK:   [[FN:%.*]] = function_ref @[[THUNK2:_T014objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTcTO]]
   // CHECK:   [[METATYPE:%.*]] = metatype $@thick T.Type
+  // CHECK:   [[FN:%.*]] = function_ref @[[THUNK2:_T014objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTcTO]]
   // CHECK:   [[METHOD:%.*]] = apply [[FN]]<T>([[METATYPE]])
   // CHECK:   destroy_value [[METHOD:%.*]]
   _ = T.mince
@@ -124,8 +124,8 @@
   // CHECK: bb0([[ARG:%.*]] : @owned $NSRuncing):
   // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK:   [[OPENED_ARG:%.*]] = open_existential_ref [[BORROWED_ARG]] : $NSRuncing to $[[OPENED:@opened(.*) NSRuncing]]
-  // CHECK:   [[FN:%.*]] = function_ref @_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO
   // CHECK:   [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
+  // CHECK:   [[FN:%.*]] = function_ref @_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO
   // CHECK:   [[RESULT:%.*]] = apply [[FN]]<[[OPENED]]>([[OPENED_ARG_COPY]])
   // CHECK:   destroy_value [[RESULT]]
   // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
diff --git a/test/SILGen/objc_required_designated_init.swift b/test/SILGen/objc_required_designated_init.swift
index 546aa21..fad2ba2 100644
--- a/test/SILGen/objc_required_designated_init.swift
+++ b/test/SILGen/objc_required_designated_init.swift
@@ -1,19 +1,39 @@
 // RUN: %empty-directory(%t)
 // RUN: %target-swift-frontend -emit-module -enable-sil-ownership %S/Inputs/objc_required_designated_init_2.swift -module-name Booms -o %t/Booms.swiftmodule -import-objc-header %S/Inputs/objc_required_designated_init.h
-// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -verify %s -import-objc-header %S/Inputs/objc_required_designated_init.h
+// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -verify %s -import-objc-header %S/Inputs/objc_required_designated_init.h | %FileCheck %s
+// RUN: %target-swift-frontend -I %t -emit-ir %s -import-objc-header %S/Inputs/objc_required_designated_init.h
 
 // REQUIRES: objc_interop
 
 import Booms
 
-class Baboom: Boom {
+class Baboom : Boom {
+  @objc dynamic required init() {
+    super.init()
+  }
+}
+
+class BigBadaBoom<V> : Badaboom<V> {
   required init() {
     super.init()
   }
 }
 
-class BigBadaBoom<V>: Badaboom<V> {
-  required init() {
-    super.init()
-  }
+class Root {
+  @objc dynamic required init() {}
 }
+
+// CHECK-LABEL: sil_vtable Baboom {
+// CHECK:   #Boom.init!allocator.1: (Boom.Type) -> () -> Boom : _T029objc_required_designated_init6BaboomCACycfC [override]
+// CHECK:   #Baboom.deinit!deallocator: _T029objc_required_designated_init6BaboomCfD
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable BigBadaBoom {
+// CHECK:   #Badaboom.init!allocator.1: <U> (Badaboom<U>.Type) -> () -> Badaboom<U> : _T029objc_required_designated_init11BigBadaBoomCACyxGycfC [override]
+// CHECK:   #BigBadaBoom.deinit!deallocator: _T029objc_required_designated_init11BigBadaBoomCfD
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable Root {
+// CHECK:   #Root.init!allocator.1: (Root.Type) -> () -> Root : _T029objc_required_designated_init4RootCACycfC
+// CHECK:   #Root.deinit!deallocator: _T029objc_required_designated_init4RootCfD
+// CHECK: }
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index 91ce7d3..7651ba2 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -106,7 +106,7 @@
   // CHECK:   [[RES:%.*]] = apply [[FR]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
   // CHECK:   end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
   // CHECK:   destroy_value [[THIS_COPY]]
-  // CHECK:   return [[RES]] : $(), scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
+  // CHECK:   return [[RES]] : $(), loc {{.*}}, scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
   // CHECK: } // end sil function '_T011objc_thunks6HoozitC15typicalPropertySo5GizmoCvsTo'
 
   // CHECK-LABEL: sil hidden @_T011objc_thunks6HoozitC15typicalPropertySo5GizmoCvs
@@ -492,10 +492,10 @@
   override init() { i = 5 }
 
   // CHECK-LABEL: sil hidden @_T011objc_thunks15DesignatedStubsCSQyACGSi7bellsOn_tcfc
-  // CHECK: function_ref @_T0s25_unimplementedInitializers5NeverOs12StaticStringV9className_AE04initG0AE4fileSu4lineSu6columntF
   // CHECK: string_literal utf8 "objc_thunks.DesignatedStubs"
   // CHECK: string_literal utf8 "init(bellsOn:)"
   // CHECK: string_literal utf8 "{{.*}}objc_thunks.swift"
+  // CHECK: function_ref @_T0s25_unimplementedInitializers5NeverOs12StaticStringV9className_AE04initG0AE4fileSu4lineSu6columntF
   // CHECK: return
 
   // CHECK-NOT: sil hidden @_TFCSo15DesignatedStubsc{{.*}}
diff --git a/test/SILGen/opaque_ownership.swift b/test/SILGen/opaque_ownership.swift
index f1c6b63..4ff4926 100644
--- a/test/SILGen/opaque_ownership.swift
+++ b/test/SILGen/opaque_ownership.swift
@@ -242,15 +242,15 @@
 // ---
 // CHECK-LABEL: sil @_T0s7EnumSeqV12makeIterators0A4IterVy0D0QzGyF : $@convention(method) <Base where Base : Seq> (@in_guaranteed EnumSeq<Base>) -> @out EnumIter<Base.Iterator> {
 // CHECK: bb0(%0 : @guaranteed $EnumSeq<Base>):
-// CHECK: [[FN:%.*]] = function_ref @_T0s8EnumIterVAByxGx5_base_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
 // CHECK:  [[MT:%.*]] = metatype $@thin EnumIter<Base.Iterator>.Type
-// CHECK:  [[WT:%.*]] = witness_method $Base, #Seq.makeIterator!1 : <Self where Self : Seq> (Self) -> () -> Self.Iterator : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
 // CHECK:  [[FIELD:%.*]] = struct_extract %0 : $EnumSeq<Base>, #EnumSeq._base
 // CHECK:  [[COPY:%.*]] = copy_value [[FIELD]] : $Base
 // CHECK:  [[BORROW:%.*]] = begin_borrow [[COPY]] : $Base
+// CHECK:  [[WT:%.*]] = witness_method $Base, #Seq.makeIterator!1 : <Self where Self : Seq> (Self) -> () -> Self.Iterator : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
 // CHECK:  [[ITER:%.*]] = apply [[WT]]<Base>([[BORROW]]) : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
 // CHECK:  end_borrow [[BORROW]] from [[COPY]] : $Base, $Base
 // CHECK:  destroy_value [[COPY]] : $Base
+// CHECK: [[FN:%.*]] = function_ref @_T0s8EnumIterVAByxGx5_base_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
 // CHECK:  [[RET:%.*]] = apply [[FN]]<Base.Iterator>([[ITER]], [[MT]]) : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
 // CHECK:  return [[RET]] : $EnumIter<Base.Iterator>
 // CHECK-LABEL: } // end sil function '_T0s7EnumSeqV12makeIterators0A4IterVy0D0QzGyF'
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index 41815bc..d5a8939 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -255,8 +255,8 @@
 // ---
 // CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s070__materializeSelfyx1t_tRlzCAA3FooRzlF : $@convention(thin) <T where T : AnyObject, T : Foo> (@owned T) -> () {
 // CHECK: bb0([[ARG:%.*]] : $T):
-// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $T, #Foo.foo!1 : <Self where Self : Foo> (Self) -> () -> () : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
 // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $T, #Foo.foo!1 : <Self where Self : Foo> (Self) -> () -> () : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
 // CHECK: apply [[WITNESS_METHOD]]<T>([[BORROWED_ARG]]) : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
 // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
 // CHECK: destroy_value [[ARG]] : $T
diff --git a/test/SILGen/optional-cast.swift b/test/SILGen/optional-cast.swift
index 221181b..a5a6e32 100644
--- a/test/SILGen/optional-cast.swift
+++ b/test/SILGen/optional-cast.swift
@@ -221,7 +221,7 @@
   // CHECK: bb0(%0 : @trivial $*Optional<T>, %1 : @trivial $TestAddressOnlyStruct<T>):
   // CHECK: [[TMPBUF:%.*]] = alloc_stack $Optional<T>
   // CHECK-NEXT: copy_addr %0 to [initialization] [[TMPBUF]]
-  // CHECK-NEXT: apply {{.*}}<T>([[TMPBUF]], %1)
+  // CHECK: apply {{.*}}<T>([[TMPBUF]], %1)
   func testCall(_ a : T!) {
     f(a)
   }
diff --git a/test/SILGen/partial_apply_generic.swift b/test/SILGen/partial_apply_generic.swift
index 70dbbfc..e2fd33e 100644
--- a/test/SILGen/partial_apply_generic.swift
+++ b/test/SILGen/partial_apply_generic.swift
@@ -35,9 +35,9 @@
 
 // CHECK-LABEL: sil hidden @_T021partial_apply_generic16getInstanceFunc1{{[_0-9a-zA-Z]*}}F
 func getInstanceFunc1<T: Foo>(t: T) -> () -> () {
-// CHECK: [[REF:%.*]] = function_ref @_T021partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT: alloc_stack $T
+// CHECK: alloc_stack $T
 // CHECK-NEXT: copy_addr %0 to [initialization]
+// CHECK: [[REF:%.*]] = function_ref @_T021partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT: apply [[REF]]<T>
   return t.instanceFunc
 // CHECK-NEXT: dealloc_stack
diff --git a/test/SILGen/partial_apply_super.swift b/test/SILGen/partial_apply_super.swift
index cdc867f..512f820 100644
--- a/test/SILGen/partial_apply_super.swift
+++ b/test/SILGen/partial_apply_super.swift
@@ -31,12 +31,12 @@
 class Child : Parent {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC6methodyyF : $@convention(method) (@guaranteed Child) -> ()
   // CHECK: bb0([[SELF:%.*]] : $Child):
-  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:   [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $Child to $Parent
   // CHECK:   [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC6methodyyFTcTd : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
   // CHECK:   [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
   // CHECK:   [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super5ChildC6methodyyF'
   override func method() {
@@ -44,11 +44,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC11classMethodyyFZ : $@convention(method) (@thick Child.Type) -> () {
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC11classMethodyyFZTcTd : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
   // CHECK:   [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -56,12 +56,12 @@
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC20callFinalSuperMethodyyF : $@convention(method) (@guaranteed Child) -> ()
   // CHECK: bb0([[SELF:%.*]] : $Child):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $Child to $Parent
   // CHECK:     [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC11finalMethodyyFTc : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
   // CHECK:     [[APPLIED_SELF:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[APPLIED_SELF]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super5ChildC20callFinalSuperMethodyyF'
   func callFinalSuperMethod() {
@@ -69,11 +69,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC25callFinalSuperClassMethodyyFZ : $@convention(method) (@thick Child.Type) -> ()
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC16finalClassMethodyyFZTc : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
   // CHECK: [[APPLIED_SELF:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_SELF]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   class func callFinalSuperClassMethod() {
     doFoo(super.finalClassMethod)
@@ -86,12 +86,12 @@
   }
   // CHECK-LABEL: sil hidden @_T019partial_apply_super12GenericChildC6methodyyF : $@convention(method) <A> (@guaranteed GenericChild<A>) -> ()
   // CHECK: bb0([[SELF:%.*]] : $GenericChild<A>):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChild<A> to $GenericParent<A>
   // CHECK:     [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super13GenericParentC6methodyyFTcTd : $@convention(thin) <τ_0_0> (@owned GenericParent<τ_0_0>) -> @owned @callee_owned () -> ()
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(thin) <τ_0_0> (@owned GenericParent<τ_0_0>) -> @owned @callee_owned () -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super12GenericChildC6methodyyF'
   override func method() {
@@ -99,12 +99,12 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super12GenericChildC11classMethodyyFZ : $@convention(method) <A> (@thick GenericChild<A>.Type) -> ()
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChild<A>.Type to $@thick GenericParent<A>.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super13GenericParentC11classMethodyyFZTcTd : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
-  // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply %4<A>(%3) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
+  // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
-  // CHECK: apply %2([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
+  // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
   }
@@ -113,7 +113,6 @@
 class ChildToFixedOutsideParent : OutsideParent {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super25ChildToFixedOutsideParentC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $ChildToFixedOutsideParent):
-  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:   [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToFixedOutsideParent to $OutsideParent
   // CHECK:   [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -122,6 +121,7 @@
   // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:   [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideParent) -> ()
   // CHECK:   [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super25ChildToFixedOutsideParentC6methodyyF'
   override func method() {
@@ -129,11 +129,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super25ChildToFixedOutsideParentC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick ChildToFixedOutsideParent.Type to $@thick OutsideParent.Type
-  // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}} // user: %5
+  // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}}
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideParent.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -143,7 +143,6 @@
 class ChildToResilientOutsideParent : ResilientOutsideParent {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super29ChildToResilientOutsideParentC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $ChildToResilientOutsideParent):
-  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:   [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToResilientOutsideParent to $ResilientOutsideParent
   // CHECK:   [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -152,6 +151,7 @@
   // CHECK:   end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:   [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
   // CHECK:   [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:   apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super29ChildToResilientOutsideParentC6methodyyF'
   override func method() {
@@ -159,11 +159,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super29ChildToResilientOutsideParentC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick ChildToResilientOutsideParent.Type to $@thick ResilientOutsideParent.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToResilientOutsideParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -173,7 +173,6 @@
 class GrandchildToFixedOutsideChild : OutsideChild {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $GrandchildToFixedOutsideChild):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToFixedOutsideChild to $OutsideChild
   // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -182,6 +181,7 @@
   // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideChild) -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF'
   override func method() {
@@ -189,11 +189,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super29GrandchildToFixedOutsideChildC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GrandchildToFixedOutsideChild.Type to $@thick OutsideChild.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GrandchildToFixedOutsideChild.Type, #OutsideChild.classMethod!1 : (OutsideChild.Type) -> () -> (), $@convention(method) (@thick OutsideChild.Type) -> ()
-  // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply %4(%3) : $@convention(method) (@thick OutsideChild.Type) -> ()
+  // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideChild.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -203,7 +203,6 @@
 class GrandchildToResilientOutsideChild : ResilientOutsideChild {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $GrandchildToResilientOutsideChild):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToResilientOutsideChild to $ResilientOutsideChild
   // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -212,6 +211,7 @@
   // CHEC:      end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF'
   override func method() {
@@ -219,11 +219,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super33GrandchildToResilientOutsideChildC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GrandchildToResilientOutsideChild.Type to $@thick ResilientOutsideChild.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GrandchildToResilientOutsideChild.Type, #ResilientOutsideChild.classMethod!1 : (ResilientOutsideChild.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -233,7 +233,6 @@
 class GenericChildToFixedGenericOutsideParent<A> : GenericOutsideParent<A> {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $GenericChildToFixedGenericOutsideParent<A>):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A> to $GenericOutsideParent<A>
   // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -242,6 +241,7 @@
   // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF'
   override func method() {
@@ -249,11 +249,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super019GenericChildToFixedD13OutsideParentC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type to $@thick GenericOutsideParent<A>.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type, #GenericOutsideParent.classMethod!1 : <A> (GenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
@@ -263,7 +263,6 @@
 class GenericChildToResilientGenericOutsideParent<A> : ResilientGenericOutsideParent<A> {
   // CHECK-LABEL: sil hidden @_T019partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF
   // CHECK: bb0([[SELF:%.*]] : $GenericChildToResilientGenericOutsideParent<A>):
-  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A> to $ResilientGenericOutsideParent<A>
   // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -272,6 +271,7 @@
   // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
   // CHECK:     [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK:     apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF'
   override func method() {
@@ -279,11 +279,11 @@
   }
 
   // CHECK-LABEL: sil hidden @_T019partial_apply_super023GenericChildToResilientD13OutsideParentC11classMethodyyFZ
-  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type to $@thick ResilientGenericOutsideParent<A>.Type
   // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type, #ResilientGenericOutsideParent.classMethod!1 : <A> (ResilientGenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
   // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+  // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
   override class func classMethod() {
     doFoo(super.classMethod)
diff --git a/test/SILGen/pointer_conversion.swift b/test/SILGen/pointer_conversion.swift
index e8ab640..4e3a012 100644
--- a/test/SILGen/pointer_conversion.swift
+++ b/test/SILGen/pointer_conversion.swift
@@ -31,33 +31,33 @@
   // CHECK: apply [[TAKES_MUTABLE_POINTER]]([[MP]])
 
   takesMutableVoidPointer(mp)
-  // CHECK: [[TAKES_MUTABLE_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesMutableVoidPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+  // CHECK: [[TAKES_MUTABLE_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesMutableVoidPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE_VOID_POINTER]]
 
   takesMutableRawPointer(mp)
-  // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+  // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
   // CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]
 
   takesConstPointer(mp)
-  // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafePointer<Int>>
+  // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
   // CHECK: apply [[TAKES_CONST_POINTER]]
 
   takesConstVoidPointer(mp)
-  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
   // CHECK: apply [[TAKES_CONST_VOID_POINTER]]
 
   takesConstRawPointer(mp)
-  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
   // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
 
   takesConstPointer(cp)
@@ -65,21 +65,21 @@
   // CHECK: apply [[TAKES_CONST_POINTER]]([[CP]])
 
   takesConstVoidPointer(cp)
-  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
   // CHECK: apply [[TAKES_CONST_VOID_POINTER]]
 
   takesConstRawPointer(cp)
-  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
   // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
 
   takesConstRawPointer(mrp)
-  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer, UnsafeRawPointer>
+  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
   // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
 }
 
@@ -88,43 +88,42 @@
   var ints = [1,2,3]
 
   takesMutablePointer(&ints)
-  // CHECK: [[TAKES_MUTABLE_POINTER:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @_T0s37_convertMutableArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_MUTABLE]]<Int, UnsafeMutablePointer<Int>>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeMutablePointer<Int> on [[OWNER]]
+  // CHECK: [[TAKES_MUTABLE_POINTER:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesConstPointer(ints)
-  // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
   // CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_CONST]]<Int, UnsafePointer<Int>>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafePointer<Int> on [[OWNER]]
+  // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
   // CHECK: apply [[TAKES_CONST_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesMutableRawPointer(&ints)
-  // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
   // CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @_T0s37_convertMutableArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_MUTABLE]]<Int, UnsafeMutableRawPointer>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]]
+  // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
   // CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesConstRawPointer(ints)
-  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
   // CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_CONST]]<Int, UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
   // CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesOptConstPointer(ints, and: sideEffect1())
-  // CHECK: [[TAKES_OPT_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF :
   // CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
   // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
   // CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
@@ -132,6 +131,7 @@
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafePointer<Int> on [[OWNER]]
   // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.some!enumelt.1, [[DEPENDENT]]
+  // CHECK: [[TAKES_OPT_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF :
   // CHECK: apply [[TAKES_OPT_CONST_POINTER]]([[OPTPTR]], [[RESULT1]])
   // CHECK: destroy_value [[OWNER]]
 }
@@ -139,25 +139,24 @@
 // CHECK-LABEL: sil hidden @_T018pointer_conversion15stringToPointerySSF 
 func stringToPointer(_ s: String) {
   takesConstVoidPointer(s)
-  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySV{{[_0-9a-zA-Z]*}}F
   // CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_STRING]]<UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+  // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySV{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_CONST_VOID_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesConstRawPointer(s)
-  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySV{{[_0-9a-zA-Z]*}}F
   // CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: [[OWNER:%.*]] = apply [[CONVERT_STRING]]<UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+  // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySV{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
   // CHECK: destroy_value [[OWNER]]
 
   takesOptConstRawPointer(s, and: sideEffect1())
-  // CHECK: [[TAKES_OPT_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF :
   // CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
   // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
   // CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
@@ -165,6 +164,7 @@
   // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
   // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
   // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEPENDENT]]
+  // CHECK: [[TAKES_OPT_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF :
   // CHECK: apply [[TAKES_OPT_CONST_RAW_POINTER]]([[OPTPTR]], [[RESULT1]])
   // CHECK: destroy_value [[OWNER]]
 }
@@ -175,11 +175,11 @@
   // CHECK: [[INT:%.*]] = alloc_box ${ var Int }
   // CHECK: [[PB:%.*]] = project_box [[INT]]
   takesMutablePointer(&int)
-  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
   // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>({{%.*}}, [[POINTER]])
+  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE]]
 
   var logicalInt: Int {
@@ -187,29 +187,29 @@
     set { }
   }
   takesMutablePointer(&logicalInt)
-  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[GETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
   // CHECK: apply [[GETTER]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>
+  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE]]
   // CHECK: [[SETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
   // CHECK: apply [[SETTER]]
 
   takesMutableRawPointer(&int)
-  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
   // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>({{%.*}}, [[POINTER]])
+  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE]]
 
   takesMutableRawPointer(&logicalInt)
-  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[GETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
   // CHECK: apply [[GETTER]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>
+  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_MUTABLE]]
   // CHECK: [[SETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
   // CHECK: apply [[SETTER]]
@@ -227,15 +227,14 @@
   // CHECK: [[VAR:%.*]] = alloc_box ${ var C }
   // CHECK: [[PB:%.*]] = project_box [[VAR]]
   takesPlusOnePointer(&c)
-  // CHECK: [[TAKES_PLUS_ONE:%.*]] = function_ref @_T018pointer_conversion19takesPlusOnePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
   // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+  // CHECK: [[TAKES_PLUS_ONE:%.*]] = function_ref @_T018pointer_conversion19takesPlusOnePointer{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[TAKES_PLUS_ONE]]
 
   takesPlusZeroPointer(&c)
-  // CHECK: [[TAKES_PLUS_ZERO:%.*]] = function_ref @_T018pointer_conversion20takesPlusZeroPointerys026AutoreleasingUnsafeMutableF0VyAA1CCGF
   // CHECK: [[WRITEBACK:%.*]] = alloc_stack $@sil_unmanaged C
   // CHECK: [[OWNED:%.*]] = load_borrow [[PB]]
   // CHECK: [[UNOWNED:%.*]] = ref_to_unmanaged [[OWNED]]
@@ -243,6 +242,7 @@
   // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITEBACK]]
   // CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[CONVERT]]<AutoreleasingUnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+  // CHECK: [[TAKES_PLUS_ZERO:%.*]] = function_ref @_T018pointer_conversion20takesPlusZeroPointerys026AutoreleasingUnsafeMutableF0VyAA1CCGF
   // CHECK: apply [[TAKES_PLUS_ZERO]]
   // CHECK: [[UNOWNED_OUT:%.*]] = load [trivial] [[WRITEBACK]]
   // CHECK: [[OWNED_OUT:%.*]] = unmanaged_to_ref [[UNOWNED_OUT]]
@@ -280,23 +280,23 @@
   // CHECK: store {{.*}} to [init] [[ARRAY]]
   var array = [Int]()
 
-  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointerySpySiG_Si3andtF
   // CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
   // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
   // CHECK: [[SIDE2:%.*]] = function_ref @_T018pointer_conversion11sideEffect2SiyF
   // CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
   // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[ARRAY]] : $*Array<Int>
+  // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointerySpySiG_Si3andtF
   // CHECK: apply [[TAKES_MUTABLE]]({{.*}}, [[RESULT2]])
   // CHECK: strong_unpin
   // CHECK: end_access [[ACCESS]]
   takesMutablePointer(&array[sideEffect1()], and: sideEffect2())
 
-  // CHECK: [[TAKES_CONST:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiG_Si3andtF
   // CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
   // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
   // CHECK: [[SIDE2:%.*]] = function_ref @_T018pointer_conversion11sideEffect2SiyF
   // CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
   // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ARRAY]] : $*Array<Int>
+  // CHECK: [[TAKES_CONST:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiG_Si3andtF
   // CHECK: apply [[TAKES_CONST]]({{.*}}, [[RESULT2]])
   // CHECK: end_access [[ACCESS]]
   takesConstPointer(&array[sideEffect1()], and: sideEffect2())
@@ -305,7 +305,6 @@
 // rdar://problem/31542269
 // CHECK-LABEL: sil hidden @_T018pointer_conversion20optArrayToOptPointerySaySiGSg5array_tF
 func optArrayToOptPointer(array: [Int]?) {
-  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF
   // CHECK:   [[BORROW:%.*]] = begin_borrow %0
   // CHECK:   [[COPY:%.*]] = copy_value [[BORROW]]
   // CHECK:   [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -324,6 +323,7 @@
   // CHECK:   br [[CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafePointer<Int>>, [[OWNER]] : $Optional<AnyObject>)
   // CHECK: [[CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafePointer<Int>>, [[OWNER:%.*]] : $Optional<AnyObject>):
   // CHECK:   [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafePointer<Int>> on [[OWNER]]
+  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF
   // CHECK:   apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
   // CHECK:   destroy_value [[OWNER]]
   // CHECK:   end_borrow [[BORROW]]
@@ -337,7 +337,6 @@
 
 // CHECK-LABEL: sil hidden @_T018pointer_conversion013optOptArrayTodD7PointerySaySiGSgSg5array_tF
 func optOptArrayToOptOptPointer(array: [Int]??) {
-  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD12ConstPointerySPySiGSgSg_Si3andtF
   // CHECK:   [[BORROW:%.*]] = begin_borrow %0
   // CHECK:   [[COPY:%.*]] = copy_value [[BORROW]]
   // CHECK:   [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -367,6 +366,7 @@
   // CHECK:   br [[SOME_CONT_BB:bb[0-9]+]]([[OPTOPTPTR]] : $Optional<Optional<UnsafePointer<Int>>>, [[OWNER]] : $Optional<AnyObject>)
   // CHECK: [[SOME_CONT_BB]]([[OPTOPTPTR:%.*]] : $Optional<Optional<UnsafePointer<Int>>>, [[OWNER:%.*]] : $Optional<AnyObject>):
   // CHECK:   [[OPTOPTDEP:%.*]] = mark_dependence [[OPTOPTPTR]] : $Optional<Optional<UnsafePointer<Int>>> on [[OWNER]]
+  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD12ConstPointerySPySiGSgSg_Si3andtF
   // CHECK:   apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
   // CHECK:   destroy_value [[OWNER]]
   // CHECK:   end_borrow [[BORROW]]
@@ -384,7 +384,6 @@
 
 // CHECK-LABEL: sil hidden @_T018pointer_conversion21optStringToOptPointerySSSg6string_tF
 func optStringToOptPointer(string: String?) {
-  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF
   // CHECK:   [[BORROW:%.*]] = begin_borrow %0
   // CHECK:   [[COPY:%.*]] = copy_value [[BORROW]]
   // CHECK:   [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -403,6 +402,7 @@
   // CHECK:   br [[CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafeRawPointer>, [[OWNER]] : $Optional<AnyObject>)
   // CHECK: [[CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafeRawPointer>, [[OWNER:%.*]] : $Optional<AnyObject>):
   // CHECK:   [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafeRawPointer> on [[OWNER]]
+  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF
   // CHECK:   apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
   // CHECK:   destroy_value [[OWNER]]
   // CHECK:   end_borrow [[BORROW]]
@@ -416,7 +416,6 @@
 
 // CHECK-LABEL: sil hidden @_T018pointer_conversion014optOptStringTodD7PointerySSSgSg6string_tF
 func optOptStringToOptOptPointer(string: String??) {
-  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD15ConstRawPointerySVSgSg_Si3andtF
   // CHECK:   [[BORROW:%.*]] = begin_borrow %0
   // CHECK:   [[COPY:%.*]] = copy_value [[BORROW]]
   // CHECK:   [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -447,6 +446,7 @@
   // CHECK:   br [[SOME_CONT_BB:bb[0-9]+]]([[OPTOPTPTR]] : $Optional<Optional<UnsafeRawPointer>>, [[OWNER]] : $Optional<AnyObject>)
   // CHECK: [[SOME_CONT_BB]]([[OPTOPTPTR:%.*]] : $Optional<Optional<UnsafeRawPointer>>, [[OWNER:%.*]] : $Optional<AnyObject>):
   // CHECK:   [[OPTOPTDEP:%.*]] = mark_dependence [[OPTOPTPTR]] : $Optional<Optional<UnsafeRawPointer>> on [[OWNER]]
+  // CHECK:   [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD15ConstRawPointerySVSgSg_Si3andtF
   // CHECK:   apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
   // CHECK:   destroy_value [[OWNER]]
   // CHECK:   end_borrow [[BORROW]]
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 35058c5..443245b 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -123,8 +123,7 @@
   // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
   // CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]] : $RefSubclass
   // CHECK: [[R_SUP:%[0-9]+]] = upcast [[ARG1_COPY]] : $RefSubclass to $Ref
-  // CHECK: [[BORROWED_R_SUP:%.*]] = begin_borrow [[R_SUP]]
-  // CHECK: [[FN:%[0-9]+]] = class_method [[BORROWED_R_SUP]] : $Ref, #Ref.y!setter.1 : (Ref) -> (Int) -> (), $@convention(method) (Int, @guaranteed Ref) -> ()
+  // CHECK: [[FN:%[0-9]+]] = class_method [[R_SUP]] : $Ref, #Ref.y!setter.1 : (Ref) -> (Int) -> (), $@convention(method) (Int, @guaranteed Ref) -> ()
   // CHECK: apply [[FN]]([[ARG2]], [[R_SUP]]) :
   // CHECK: destroy_value [[R_SUP]]
   // CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
@@ -160,8 +159,7 @@
   return class_rvalue().y
   // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T010properties12class_rvalueAA3RefCyF
   // CHECK: [[CLASS:%[0-9]+]] = apply [[FUNC]]()
-  // CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
-  // CHECK: [[FN:%[0-9]+]] = class_method [[BORROWED_CLASS]] : $Ref, #Ref.y!getter.1
+  // CHECK: [[FN:%[0-9]+]] = class_method [[CLASS]] : $Ref, #Ref.y!getter.1
   // CHECK: [[RET:%[0-9]+]] = apply [[FN]]([[CLASS]])
   // CHECK: return [[RET]]
 }
@@ -180,8 +178,8 @@
 func logical_struct_set(_ value: inout Val, z: Int) {
   // CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z:%[0-9]+]] : $Int):
   value.z = z
-  // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
+  // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
   // CHECK: apply [[Z_SET_METHOD]]([[Z]], [[WRITE]])
   // CHECK: return
 }
@@ -190,9 +188,9 @@
 func logical_struct_in_tuple_set(_ value: inout (Int, Val), z: Int) {
   // CHECK: bb0([[VAL:%[0-9]+]] : $*(Int, Val), [[Z:%[0-9]+]] : $Int):
   value.1.z = z
-  // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
   // CHECK: [[VAL_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1
+  // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
   // CHECK: apply [[Z_SET_METHOD]]([[Z]], [[VAL_1]])
   // CHECK: return
 }
@@ -221,9 +219,9 @@
   // -- val.ref.val_prop.z_tuple
   // CHECK: [[V_R_VP_Z_TUPLE_MAT:%[0-9]+]] = alloc_stack $(Int, Int)
   // CHECK: [[LD:%[0-9]+]] = load_borrow [[VAL_REF_VAL_PROP_MAT]]
-  // CHECK: [[GET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
   // CHECK: [[A0:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 0
   // CHECK: [[A1:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 1
+  // CHECK: [[GET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
   // CHECK: [[V_R_VP_Z_TUPLE:%[0-9]+]] = apply [[GET_Z_TUPLE_METHOD]]([[LD]])
   // CHECK: [[T0:%.*]] = tuple_extract [[V_R_VP_Z_TUPLE]] : {{.*}}, 0
   // CHECK: [[T1:%.*]] = tuple_extract [[V_R_VP_Z_TUPLE]] : {{.*}}, 1
@@ -268,9 +266,9 @@
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
   // CHECK: [[Z_TUPLE_MATERIALIZED:%[0-9]+]] = alloc_stack $(Int, Int)
   // CHECK: [[VAL1:%[0-9]+]] = load_borrow [[WRITE]]
-  // CHECK: [[Z_GET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
   // CHECK: [[A0:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 0
   // CHECK: [[A1:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 1
+  // CHECK: [[Z_GET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
   // CHECK: [[Z_TUPLE:%[0-9]+]] = apply [[Z_GET_METHOD]]([[VAL1]])
   // CHECK: [[T0:%.*]] = tuple_extract [[Z_TUPLE]] : {{.*}}, 0
   // CHECK: [[T1:%.*]] = tuple_extract [[Z_TUPLE]] : {{.*}}, 1
@@ -371,8 +369,8 @@
   // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
   // CHECK: [[PB:%.*]] = project_box [[XADDR]]
   inout_arg(&x)
-  // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @_T010properties9inout_arg{{[_0-9a-zA-Z]*}}F
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+  // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @_T010properties9inout_arg{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[INOUT_ARG]]([[WRITE]])
 }
 
@@ -399,8 +397,8 @@
   v[i] = x
   // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
   // CHECK: [[PB:%.*]] = project_box [[VADDR]]
-  // CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV{{[_0-9a-zA-Z]*}}is
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+  // CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV{{[_0-9a-zA-Z]*}}is
   // CHECK: apply [[SUBSCRIPT_SET_METHOD]]([[X]], [[I]], [[WRITE]])
 }
 
@@ -515,12 +513,11 @@
 
       takeInt(a)
 
-      // CHECK-NEXT: // function_ref properties.takeInt
-      // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
       // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %1
       // CHECK-NEXT: [[FIELDPTR:%.*]] = struct_element_addr [[READ]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
       // CHECK-NEXT: [[A:%.*]] = load [trivial] [[FIELDPTR]] : $*Int
       // CHECK-NEXT: end_access [[READ]]
+      // CHECK: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
       // CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
 
       takeInt(newA)
@@ -539,12 +536,12 @@
 
       takeInt(a)
 
-      // CHECK-NEXT: // function_ref properties.takeInt(Swift.Int) -> ()
-      // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
       // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %1
       // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[READ]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
       // CHECK-NEXT: [[A:%.*]] = load [trivial] [[AADDR]] : $*Int
       // CHECK-NEXT: end_access [[READ]]
+      // CHECK-NEXT: // function_ref properties.takeInt(Swift.Int) -> ()
+      // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
       // CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
 
       a = zero  // reassign, but don't infinite loop.
@@ -589,18 +586,18 @@
   // CHECK-NEXT: end_access [[READ]]
   // CHECK-NEXT: debug_value [[OLDVAL]] : $Int, let, name "tmp"
 
+  // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
   // CHECK-NEXT: // function_ref {{.*}}.DidSetWillSetTests.a.willset : Swift.Int
   // CHECK-NEXT: [[WILLSETFN:%.*]] = function_ref @_T010properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
-  // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
   // CHECK-NEXT:  apply [[WILLSETFN]](%0, [[WRITE]]) : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
   // CHECK-NEXT: end_access [[WRITE]]
   // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
   // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
   // CHECK-NEXT: assign %0 to [[AADDR]] : $*Int
   // CHECK-NEXT: end_access [[WRITE]]
+  // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
   // CHECK-NEXT: // function_ref {{.*}}.DidSetWillSetTests.a.didset : Swift.Int
   // CHECK-NEXT: [[DIDSETFN:%.*]] = function_ref @_T010properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
-  // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
   // CHECK-NEXT: apply [[DIDSETFN]]([[OLDVAL]], [[WRITE]]) : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
 
   // CHECK-LABEL: sil hidden @_T010properties010DidSetWillC5TestsV{{[_0-9a-zA-Z]*}}fC
@@ -734,9 +731,7 @@
         // CHECK:  [[BASEPTR:%[0-9]+]] = upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
         // CHECK: load{{.*}}Int
         // CHECK-NEXT: end_access {{.*}} : $*Int
-        // CHECK-NEXT: begin_borrow {{.*}} : $rdar16151899Base
         // CHECK-NEXT: [[SETTER:%[0-9]+]] = class_method {{.*}} : $rdar16151899Base, #rdar16151899Base.x!setter.1 : (rdar16151899Base)
-        // CHECK-NEXT: end_borrow
         // CHECK-NEXT: apply [[SETTER]]({{.*}}, [[BASEPTR]]) 
     }
 }
@@ -1191,9 +1186,7 @@
 // CHECK-NEXT:   [[C:%.*]] = load [copy] [[C_INOUT:%.*]] : $*ReferenceType
 // CHECK-NEXT:   end_access [[C_INOUT]] : $*ReferenceType
 // CHECK-NEXT:   [[C_FIELD_BOX:%.*]] = alloc_stack $NonmutatingProtocol
-// CHECK-NEXT:   [[BORROWED_C:%.*]] = begin_borrow [[C]]
-// CHECK-NEXT:   [[GETTER:%.*]] = class_method [[BORROWED_C]] : $ReferenceType, #ReferenceType.p!getter.1 : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
-// CHECK-NEXT:   end_borrow
+// CHECK-NEXT:   [[GETTER:%.*]] = class_method [[C]] : $ReferenceType, #ReferenceType.p!getter.1 : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
 // CHECK-NEXT:   apply [[GETTER]]([[C_FIELD_BOX]], [[C]]) : $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
 // CHECK-NEXT:   destroy_value [[C]] : $ReferenceType
 // CHECK-NEXT:   [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}") NonmutatingProtocol
diff --git a/test/SILGen/property_abstraction.swift b/test/SILGen/property_abstraction.swift
index 943313e..8fb926d 100644
--- a/test/SILGen/property_abstraction.swift
+++ b/test/SILGen/property_abstraction.swift
@@ -44,7 +44,6 @@
 // CHECK:   [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
 // CHECK:   store [[ARG_COPY]] to [init] [[XBOX_PB]]
 // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
-// CHECK:   [[INOUTFUNC:%.*]] = function_ref @_T020property_abstraction9inOutFunc{{[_0-9a-zA-Z]*}}F
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] [[XBOX_PB]] : $*Foo<Int, Int>
 // CHECK:   [[F_ADDR:%.*]] = struct_element_addr [[WRITE]] : $*Foo<Int, Int>, #Foo.f
 // CHECK:   [[F_SUBST_MAT:%.*]] = alloc_stack
@@ -52,6 +51,7 @@
 // CHECK:   [[REABSTRACT_FN:%.*]] = function_ref @_T0{{.*}}TR :
 // CHECK:   [[F_SUBST_IN:%.*]] = partial_apply [[REABSTRACT_FN]]([[F_ORIG]])
 // CHECK:   store [[F_SUBST_IN]] to [init] [[F_SUBST_MAT]]
+// CHECK:   [[INOUTFUNC:%.*]] = function_ref @_T020property_abstraction9inOutFunc{{[_0-9a-zA-Z]*}}F
 // CHECK:   apply [[INOUTFUNC]]([[F_SUBST_MAT]])
 // CHECK:   [[F_SUBST_OUT:%.*]] = load [take] [[F_SUBST_MAT]]
 // CHECK:   [[REABSTRACT_FN:%.*]] = function_ref @_T0{{.*}}TR :
@@ -140,10 +140,10 @@
 }
 // CHECK: sil hidden @_T020property_abstraction10setBuilder{{[_0-9a-zA-Z]*}}F : $@convention(thin) <F where F : Factory, F.Product == MyClass> (@inout F) -> ()
 // CHECK: bb0(%0 : @trivial $*F):
-// CHECK:   [[SETTER:%.*]] = witness_method $F, #Factory.builder!setter.1
 // CHECK:   [[F0:%.*]] = function_ref @_T020property_abstraction10setBuilder{{[_0-9a-zA-Z]*}} : $@convention(thin) () -> @owned MyClass
 // CHECK:   [[F1:%.*]] = thin_to_thick_function [[F0]]
 // CHECK:   [[REABSTRACTOR:%.*]] = function_ref @_T0{{.*}}TR :
 // CHECK:   [[F2:%.*]] = partial_apply [[REABSTRACTOR]]([[F1]])
 // CHECK:   [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*F
+// CHECK:   [[SETTER:%.*]] = witness_method $F, #Factory.builder!setter.1
 // CHECK:   apply [[SETTER]]<F>([[F2]], [[WRITE]])
diff --git a/test/SILGen/property_behavior_init.swift b/test/SILGen/property_behavior_init.swift
index 39b3d8b..b478742 100644
--- a/test/SILGen/property_behavior_init.swift
+++ b/test/SILGen/property_behavior_init.swift
@@ -47,13 +47,13 @@
     // CHECK: apply [[GETTER]]([[SELF]])
     _ = self.x
 
-    // CHECK: [[WHACK:%.*]] = function_ref @_T022property_behavior_init5whackyxzlF
     // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
     // CHECK: [[INOUT:%.*]] = alloc_stack
     // CHECK: [[SELF:%.*]] = load [trivial] [[WRITE]]
     // CHECK: [[GETTER:%.*]] = function_ref @_T022property_behavior_init3FooV1xSivg
     // CHECK: [[VALUE:%.*]] = apply [[GETTER]]([[SELF]])
     // CHECK: store [[VALUE]] to [trivial] [[INOUT]]
+    // CHECK: [[WHACK:%.*]] = function_ref @_T022property_behavior_init5whackyxzlF
     // CHECK: apply [[WHACK]]<Int>([[INOUT]])
     // CHECK: [[VALUE:%.*]] = load [trivial] [[INOUT]]
     // CHECK: [[SETTER:%.*]] = function_ref @_T022property_behavior_init3FooV1xSivs
diff --git a/test/SILGen/protocol_class_refinement.swift b/test/SILGen/protocol_class_refinement.swift
index 4de2ca2..f940ec6 100644
--- a/test/SILGen/protocol_class_refinement.swift
+++ b/test/SILGen/protocol_class_refinement.swift
@@ -30,51 +30,51 @@
   var x = x
   // CHECK: [[XBOX:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : ObjectUID> { var τ_0_0 } <T>
   // CHECK: [[PB:%.*]] = project_box [[XBOX]]
-  // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
   // -- call x.uid()
-  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X:%.*]] = load [copy] [[READ]]
   // CHECK: [[X_TMP:%.*]] = alloc_stack
   // CHECK: store [[X]] to [init] [[X_TMP]]
+  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
   // CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
   // CHECK: destroy_value [[X2]]
   // -- call set x.clsid
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+  // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
   // CHECK: apply [[SET_CLSID]]<T>([[UID]], [[WRITE]])
   x.clsid = x.uid()
 
-  // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
   // -- call x.uid()
-  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X:%.*]] = load [copy] [[READ]]
   // CHECK: [[X_TMP:%.*]] = alloc_stack
   // CHECK: store [[X]] to [init] [[X_TMP]]
+  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
   // CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
   // CHECK: destroy_value [[X2]]
   // -- call nextCLSID from protocol ext
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+  // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
   // CHECK: apply [[SET_NEXTCLSID]]<T>([[UID]], [[WRITE]])
   x.nextCLSID = x.uid()
 
   // -- call x.uid()
   // CHECK: [[READ1:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X1:%.*]] = load [copy] [[READ1]]
-  // CHECK: [[SET_SECONDNEXT:%.*]] = function_ref @_T025protocol_class_refinement9ObjectUIDPAAE15secondNextCLSIDSivs
   // CHECK: [[BORROWED_X1:%.*]] = begin_borrow [[X1]]
-  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X:%.*]] = load [copy] [[READ]]
   // CHECK: [[X_TMP:%.*]] = alloc_stack
   // CHECK: store [[X]] to [init] [[X_TMP]]
 
+  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
   // CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
   // CHECK: destroy_value [[X2]]
   // -- call secondNextCLSID from class-constrained protocol ext
+  // CHECK: [[SET_SECONDNEXT:%.*]] = function_ref @_T025protocol_class_refinement9ObjectUIDPAAE15secondNextCLSIDSivs
   // CHECK: apply [[SET_SECONDNEXT]]<T>([[UID]], [[BORROWED_X1]])
   // CHECK: end_borrow [[BORROWED_X1]] from [[X1]]
   // CHECK: destroy_value [[X1]]
@@ -89,33 +89,33 @@
   var x = x
   // CHECK: [[XBOX:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : Base, τ_0_0 : UID> { var τ_0_0 } <T>
   // CHECK: [[PB:%.*]] = project_box [[XBOX]]
-  // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
   // -- call x.uid()
-  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X:%.*]] = load [copy] [[READ]]
   // CHECK: [[X_TMP:%.*]] = alloc_stack
   // CHECK: store [[X]] to [init] [[X_TMP]]
+  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
   // CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
   // CHECK: destroy_value [[X2]]
   // -- call set x.clsid
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+  // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
   // CHECK: apply [[SET_CLSID]]<T>([[UID]], [[WRITE]])
   x.clsid = x.uid()
 
-  // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
   // -- call x.uid()
-  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
   // CHECK: [[X:%.*]] = load [copy] [[READ]]
   // CHECK: [[X_TMP:%.*]] = alloc_stack
   // CHECK: store [[X]] to [init] [[X_TMP]]
+  // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
   // CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
   // CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
   // CHECK: destroy_value [[X2]]
   // -- call nextCLSID from protocol ext
   // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+  // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
   // CHECK: apply [[SET_NEXTCLSID]]<T>([[UID]], [[WRITE]])
   x.nextCLSID = x.uid()
   return (x.iid, x.clsid, x.nextCLSID)
diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift
index 76eefa4..aabfc84 100644
--- a/test/SILGen/protocol_extensions.swift
+++ b/test/SILGen/protocol_extensions.swift
@@ -100,10 +100,10 @@
 func testD(_ m: MetaHolder, dd: D.Type, d: D) {
   // CHECK: [[D2:%[0-9]+]] = alloc_box ${ var D }
   // CHECK: [[RESULT:%.*]] = project_box [[D2]]
-  // CHECK: [[FN:%[0-9]+]] = function_ref @_T019protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F
   // CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
   // CHECK: [[MATERIALIZED_BORROWED_D:%[0-9]+]] = alloc_stack $D
   // CHECK: store_borrow [[BORROWED_D]] to [[MATERIALIZED_BORROWED_D]]
+  // CHECK: [[FN:%[0-9]+]] = function_ref @_T019protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FN]]<D>([[RESULT]], [[MATERIALIZED_BORROWED_D]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK-NEXT: dealloc_stack [[MATERIALIZED_BORROWED_D]]
   // CHECK-NEXT: end_borrow [[BORROWED_D]] from [[D]]
@@ -139,11 +139,11 @@
   // CHECK: dealloc_stack
   D.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: metatype $@thick D.Type
   // CHECK: alloc_stack $Box
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
@@ -174,10 +174,10 @@
   // CHECK: dealloc_stack
   dd.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
@@ -208,10 +208,10 @@
   // CHECK: dealloc_stack
   m.d.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
@@ -222,121 +222,121 @@
 
 // CHECK-LABEL: sil hidden @_T019protocol_extensions5testSyAA10MetaHolderV_AA1SVm2sstF
 func testS(_ m: MetaHolder, ss: S.Type) {
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = S.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   S.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   S.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   S.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   S.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   inout_func(&S.staticReadWrite2.number)
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = ss.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   ss.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   ss.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   ss.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   ss.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   inout_func(&ss.staticReadWrite2.number)
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = m.s.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   m.s.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   m.s.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   m.s.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   m.s.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick S.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
@@ -347,121 +347,121 @@
 
 // CHECK-LABEL: sil hidden @_T019protocol_extensions5testG{{[_0-9a-zA-Z]*}}F
 func testG<T>(_ m: GenericMetaHolder<T>, gg: G<T>.Type) {
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = G<T>.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   G<T>.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   G<T>.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   G<T>.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   G<T>.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   inout_func(&G<T>.staticReadWrite2.number)
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = gg.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   gg.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   gg.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   gg.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   gg.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   inout_func(&gg.staticReadWrite2.number)
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
   let _ = m.g.staticReadOnlyProperty
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   m.g.staticReadWrite1 = 1
 
   // CHECK: alloc_stack $Int
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
   // CHECK: dealloc_stack
   m.g.staticReadWrite1 += 1
 
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   m.g.staticReadWrite2 = Box(number: 2)
 
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
   m.g.staticReadWrite2.number += 5
 
-  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: alloc_stack $Box
-  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: metatype $@thick G<T>.Type
+  // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
   // CHECK: store
+  // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
   // CHECK: load
   // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
   // CHECK: dealloc_stack
@@ -698,11 +698,11 @@
     // CHECK:      [[SELF_BOX:%.*]] = alloc_box
     // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
     // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
-    // CHECK:      [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: InitRequirement) <τ_0_0 where τ_0_0 : InitRequirement> (@owned C, @thick τ_0_0.Type) -> @out τ_0_0
-    // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $Self
+    // CHECK:      [[SELF_BOX:%.*]] = alloc_stack $Self
     // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
     // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
     // CHECK-NEXT: [[ARG_COPY_CAST:%.*]] = upcast [[ARG_COPY]]
+    // CHECK:      [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: InitRequirement) <τ_0_0 where τ_0_0 : InitRequirement> (@owned C, @thick τ_0_0.Type) -> @out τ_0_0
     // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY_CAST]], [[SELF_TYPE]])
     // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
     // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [[SELF_BOX_ADDR]]
@@ -720,10 +720,10 @@
     // CHECK:      [[SELF_BOX:%.*]] = alloc_box
     // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
     // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
-    // CHECK:      [[DELEGATEE:%.*]] = function_ref @_T019protocol_extensions15InitRequirementPAAExAA1DC1d_tcfC
-    // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $Self
+    // CHECK:      [[SELF_BOX:%.*]] = alloc_stack $Self
     // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
     // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+    // CHECK:      [[DELEGATEE:%.*]] = function_ref @_T019protocol_extensions15InitRequirementPAAExAA1DC1d_tcfC
     // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY]], [[SELF_TYPE]])
     // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
     // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [[SELF_BOX_ADDR]]
@@ -741,11 +741,11 @@
     // CHECK:      [[SELF_BOX:%.*]] = alloc_box
     // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
     // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
-    // CHECK:      [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1
-    // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $Self
+    // CHECK:      [[SELF_BOX:%.*]] = alloc_stack $Self
     // CHECK-NEXT: [[SELF_TYPE:%.*]] = metatype $@thick Self.Type
     // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
     // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+    // CHECK:      [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1
     // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY]], [[SELF_TYPE]])
     // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
     // CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF_BOX_ADDR]]
@@ -767,10 +767,10 @@
 extension ClassInitRequirement {
   // CHECK-LABEL: sil hidden @_T019protocol_extensions20ClassInitRequirementPAAE{{[_0-9a-zA-Z]*}}fC : $@convention(method) <Self where Self : ClassInitRequirement> (@owned D, @thick Self.Type) -> @owned Self
   // CHECK:       bb0([[ARG:%.*]] : $D, [[SELF_TYPE:%.*]] : $@thick Self.Type):
-  // CHECK:         [[DELEGATEE:%.*]] = witness_method $Self, #ClassInitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: ClassInitRequirement) <τ_0_0 where τ_0_0 : ClassInitRequirement> (@owned C, @thick τ_0_0.Type) -> @owned τ_0_0
   // CHECK:         [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
   // CHECK:         [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
   // CHECK:         [[ARG_COPY_CAST:%.*]] = upcast [[ARG_COPY]]
+  // CHECK:         [[DELEGATEE:%.*]] = witness_method $Self, #ClassInitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: ClassInitRequirement) <τ_0_0 where τ_0_0 : ClassInitRequirement> (@owned C, @thick τ_0_0.Type) -> @owned τ_0_0
   // CHECK:         apply [[DELEGATEE]]<Self>([[ARG_COPY_CAST]], [[SELF_TYPE]])
   // CHECK:         end_borrow [[BORROWED_ARG]] from [[ARG]]
   
@@ -796,11 +796,11 @@
   // CHECK:       bb0([[ARG:%.*]] : $OD, [[SELF_TYPE:%.*]] : $@thick Self.Type):
   // CHECK:         [[OBJC_SELF_TYPE:%.*]] = thick_to_objc_metatype [[SELF_TYPE]]
   // CHECK:         [[SELF:%.*]] = alloc_ref_dynamic [objc] [[OBJC_SELF_TYPE]] : $@objc_metatype Self.Type, $Self
-  // CHECK:         [[WITNESS:%.*]] = witness_method [volatile] $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
   // CHECK:         [[BORROWED_ARG_1:%.*]] = begin_borrow [[ARG]]
   // CHECK:         [[BORROWED_ARG_1_UPCAST:%.*]] = upcast [[BORROWED_ARG_1]]
   // CHECK:         [[BORROWED_ARG_2:%.*]] = begin_borrow [[ARG]]
   // CHECK:         [[BORROWED_ARG_2_UPCAST:%.*]] = upcast [[BORROWED_ARG_2]]
+  // CHECK:         [[WITNESS:%.*]] = witness_method [volatile] $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
   // CHECK:         apply [[WITNESS]]<Self>([[BORROWED_ARG_1_UPCAST]], [[BORROWED_ARG_2_UPCAST]], [[SELF]])
   // CHECK:         end_borrow [[BORROWED_ARG_2]] from [[ARG]]
   // CHECK:         end_borrow [[BORROWED_ARG_1]] from [[ARG]]
@@ -828,8 +828,7 @@
     // CHECK:   [[SELF_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[SELF_META]] : $@thick Self.Type to $@objc_metatype Self.Type
     // CHECK:   [[SELF_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[SELF_META_OBJC]] : $@objc_metatype Self.Type, $Self
     // CHECK:   [[SELF_ALLOC_C:%[0-9]+]] = upcast [[SELF_ALLOC]] : $Self to $ObjCInitClass
-    // CHECK:   [[BORROWED_SELF_ALLOC_C:%.*]] = begin_borrow [[SELF_ALLOC_C]]
-    // CHECK:   [[OBJC_INIT:%[0-9]+]] = class_method [[BORROWED_SELF_ALLOC_C]] : $ObjCInitClass, #ObjCInitClass.init!initializer.1 : (ObjCInitClass.Type) -> () -> ObjCInitClass, $@convention(method) (@owned ObjCInitClass) -> @owned ObjCInitClass
+    // CHECK:   [[OBJC_INIT:%[0-9]+]] = class_method [[SELF_ALLOC_C]] : $ObjCInitClass, #ObjCInitClass.init!initializer.1 : (ObjCInitClass.Type) -> () -> ObjCInitClass, $@convention(method) (@owned ObjCInitClass) -> @owned ObjCInitClass
     // CHECK:   [[SELF_RESULT:%[0-9]+]] = apply [[OBJC_INIT]]([[SELF_ALLOC_C]]) : $@convention(method) (@owned ObjCInitClass) -> @owned ObjCInitClass
     // CHECK:   [[SELF_RESULT_AS_SELF:%[0-9]+]] = unchecked_ref_cast [[SELF_RESULT]] : $ObjCInitClass to $Self
     // CHECK:   assign [[SELF_RESULT_AS_SELF]] to [[PB_SELF_BOX]] : $*Self
diff --git a/test/SILGen/protocol_optional.swift b/test/SILGen/protocol_optional.swift
index d711925..54bca84 100644
--- a/test/SILGen/protocol_optional.swift
+++ b/test/SILGen/protocol_optional.swift
@@ -62,9 +62,9 @@
   // CHECK:   project_box [[OPT_BOX]]
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T
   // CHECK:   [[T:%[0-9]+]] = load [copy] [[READ]] : $*T
-  // CHECK:   [[INTCONV:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
   // CHECK:   [[INT64:%[0-9]+]] = metatype $@thin Int.Type
   // CHECK:   [[FIVELIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+  // CHECK:   [[INTCONV:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
   // CHECK:   [[FIVE:%[0-9]+]] = apply [[INTCONV]]([[FIVELIT]], [[INT64]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
   // CHECK:   alloc_stack $Optional<Int>
   // CHECK:   dynamic_method_br [[T]] : $T, #P1.subscript!getter.1.foreign
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 62a43d2..17af5ad 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -26,10 +26,10 @@
 // CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGet to $*[[OPENED:@opened(.*) SubscriptableGet]]
 // CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]]
 // CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet
 // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGet.subscript!getter.1
 // CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]])
 // CHECK-NEXT: destroy_addr [[ALLOCSTACK]]
-// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet
 // CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]]
 // CHECK-NEXT: return [[RESULT]]
 
@@ -103,8 +103,8 @@
 }
 // CHECK-LABEL: sil hidden @{{.*}}use_subscript_archetype_lvalue_set
 // CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
-// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!setter.1
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!setter.1
 // CHECK-NEXT: apply [[METH]]<T>(%1, %1, [[WRITE]])
 
 
@@ -133,6 +133,7 @@
 // CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetter to $*[[OPENED:@opened(.*) PropertyWithGetter]]
 // CHECK: [[COPY:%.*]] = alloc_stack $[[OPENED]]
 // CHECK-NEXT: copy_addr [[PROJ]] to [initialization] [[COPY]] : $*[[OPENED]]
+// CHECK-NEXT: end_access [[READ]] : $*PropertyWithGetter
 // CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter.1
 // CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[COPY]])
 
@@ -199,8 +200,8 @@
 }
 // CHECK-LABEL: sil hidden @{{.*}}use_property_archetype_lvalue_set
 // CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
-// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!setter.1
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!setter.1
 // CHECK-NEXT: apply [[METH]]<T>(%1, [[WRITE]])
 
 //===----------------------------------------------------------------------===//
@@ -212,9 +213,9 @@
 
 // CHECK-LABEL: sil hidden @_T09protocols27use_initializable_archetype{{[_0-9a-zA-Z]*}}F
 func use_initializable_archetype<T: Initializable>(_ t: T, i: Int) {
-  // CHECK:   [[T_INIT:%[0-9]+]] = witness_method $T, #Initializable.init!allocator.1 : {{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
   // CHECK:   [[T_RESULT:%[0-9]+]] = alloc_stack $T
   // CHECK:   [[T_META:%[0-9]+]] = metatype $@thick T.Type
+  // CHECK:   [[T_INIT:%[0-9]+]] = witness_method $T, #Initializable.init!allocator.1 : {{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
   // CHECK:   [[T_RESULT_ADDR:%[0-9]+]] = apply [[T_INIT]]<T>([[T_RESULT]], %1, [[T_META]]) : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
   // CHECK:   destroy_addr [[T_RESULT]] : $*T
   // CHECK:   dealloc_stack [[T_RESULT]] : $*T
@@ -416,7 +417,6 @@
   modify(&x.b)
 }
 // CHECK-LABEL: sil hidden @_T09protocols14modifyPropertyyxzAA0C16WithGetterSetterRzlF
-// CHECK:      [[MODIFY_FN:%.*]] = function_ref @_T09protocols6modifyySizF
 // CHECK:      [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
 // CHECK:      [[WITNESS_FN:%.*]] = witness_method $T, #PropertyWithGetterSetter.b!materializeForSet.1
 // CHECK:      [[RESULT:%.*]] = apply [[WITNESS_FN]]<T>
@@ -424,6 +424,7 @@
 // CHECK:      [[CALLBACK:%.*]] = tuple_extract [[RESULT]]
 // CHECK:      [[TEMPORARY_ADDR_TMP:%.*]] = pointer_to_address [[TEMPORARY]] : $Builtin.RawPointer to [strict] $*Int
 // CHECK:      [[TEMPORARY_ADDR:%.*]] = mark_dependence [[TEMPORARY_ADDR_TMP]] : $*Int on [[WRITE]] : $*T
+// CHECK:      [[MODIFY_FN:%.*]] = function_ref @_T09protocols6modifyySizF
 // CHECK:      apply [[MODIFY_FN]]([[TEMPORARY_ADDR]])
 // CHECK:      switch_enum [[CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2
 // CHECK:    bb1([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
diff --git a/test/SILGen/reabstract-tuple.swift b/test/SILGen/reabstract-tuple.swift
index 8a69014..6a04bc1 100644
--- a/test/SILGen/reabstract-tuple.swift
+++ b/test/SILGen/reabstract-tuple.swift
@@ -12,8 +12,6 @@
 
 // CHECK: sil @_T04main7testBoxyyF : $@convention(thin) () -> () {
 // CHECK: bb0:
-// CHECK:   // function_ref Box.__allocating_init(_:)
-// CHECK:   [[INIT_F:%.*]] = function_ref @_T04main3BoxCACyxGxcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0> // user: %26
 // CHECK:   // function_ref closure #1 in testBox()
 // CHECK:   [[CLOSURE:%.*]] = function_ref @_T04main7testBoxyyFyycfU_ : $@convention(thin) () -> ()
 // CHECK:   [[THICK:%.*]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) () -> () to $@callee_owned () -> ()
@@ -30,6 +28,8 @@
 // CHECK:   [[TUPLEB_0:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_owned (@in ()) -> @out ()), 0
 // CHECK:   [[TUPLEB_1:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_owned (@in ()) -> @out ()), 1
 // CHECK:   [[COPYB_1:%.*]] = copy_value [[TUPLEB_1]] : $@callee_owned (@in ()) -> @out ()
+// CHECK:   // function_ref Box.__allocating_init(_:)
+// CHECK:   [[INIT_F:%.*]] = function_ref @_T04main3BoxCACyxGxcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0>
 // CHECK:   [[CALL:%.*]] = apply [[INIT_F]]<(Int, () -> ())>(%{{.*}}, %{{.*}}) : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0>
 // CHECK:   end_borrow [[BORROWB]] from %{{.*}} : $(Int, @callee_owned (@in ()) -> @out ()), $(Int, @callee_owned (@in ()) -> @out ())
 // CHECK:   destroy_value [[TUPLEB]] : $(Int, @callee_owned (@in ()) -> @out ())
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index 45ce946..708cd96 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -7,10 +7,9 @@
   takeFn(liftOptional)
 }
 // CHECK:    sil hidden @_T010reabstract5test0yyF : $@convention(thin) () -> () {
-// CHECK:      [[T0:%.*]] = function_ref @_T010reabstract6takeFn{{[_0-9a-zA-Z]*}}F
 //   Emit a generalized reference to liftOptional.
 //   TODO: just emit a globalized thunk
-// CHECK-NEXT: reabstract.liftOptional
+// CHECK:      reabstract.liftOptional
 // CHECK-NEXT: [[T1:%.*]] = function_ref @_T010reabstract12liftOptional{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT: [[T2:%.*]] = thin_to_thick_function [[T1]]
 // CHECK-NEXT: [[CVT:%.*]] = convert_function [[T2]]
@@ -18,6 +17,7 @@
 // CHECK-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
 // CHECK-NEXT: [[T4:%.*]] = partial_apply [[T3]]([[CVT]])
 // CHECK-NEXT: [[CVT:%.*]] = convert_function [[T4]]
+// CHECK:      [[T0:%.*]] = function_ref @_T010reabstract6takeFn{{[_0-9a-zA-Z]*}}F
 // CHECK-NEXT: apply [[T0]]<Int>([[CVT]])
 // CHECK-NEXT: tuple ()
 // CHECK-NEXT: return
diff --git a/test/SILGen/reabstract_lvalue.swift b/test/SILGen/reabstract_lvalue.swift
index a785c11..4f8daf5 100644
--- a/test/SILGen/reabstract_lvalue.swift
+++ b/test/SILGen/reabstract_lvalue.swift
@@ -17,13 +17,13 @@
   // CHECK: [[ARG:%.*]] = function_ref @_T017reabstract_lvalue9transformSdSiF
   // CHECK: [[THICK_ARG:%.*]] = thin_to_thick_function [[ARG]]
   // CHECK: store [[THICK_ARG:%.*]] to [init] [[PB]]
-  // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
   // CHECK:  [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*@callee_owned (Int) -> Double
   // CHECK: [[ABSTRACTED_BOX:%.*]] = alloc_stack $@callee_owned (@in Int) -> @out Double
   // CHECK: [[THICK_ARG:%.*]] = load [copy] [[WRITE]]
   // CHECK: [[THUNK1:%.*]] = function_ref @_T0SiSdIexyd_SiSdIexir_TR
   // CHECK: [[ABSTRACTED_ARG:%.*]] = partial_apply [[THUNK1]]([[THICK_ARG]])
   // CHECK: store [[ABSTRACTED_ARG]] to [init] [[ABSTRACTED_BOX]]
+  // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC]]<(Int) -> Double>([[ABSTRACTED_BOX]])
   // CHECK: [[NEW_ABSTRACTED_ARG:%.*]] = load [take] [[ABSTRACTED_BOX]]
   // CHECK: [[THUNK2:%.*]] = function_ref @_T0SiSdIexir_SiSdIexyd_TR
@@ -38,10 +38,10 @@
 // CHECK-LABEL: sil hidden @_T017reabstract_lvalue0A13MetatypeInOutyyF : $@convention(thin) () -> ()
 func reabstractMetatypeInOut() {
   var thinMetatype = MyMetatypeIsThin.self
-  // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
   // CHECK: [[BOX:%.*]] = alloc_stack $@thick MyMetatypeIsThin.Type
   // CHECK: [[THICK:%.*]] = metatype $@thick MyMetatypeIsThin.Type
   // CHECK: store [[THICK]] to [trivial] [[BOX]]
+  // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
   // CHECK: apply [[FUNC]]<MyMetatypeIsThin.Type>([[BOX]])
   consumeGenericInOut(&thinMetatype)
 }
diff --git a/test/SILGen/rethrows.swift b/test/SILGen/rethrows.swift
index 671d37d..ceddf1b 100644
--- a/test/SILGen/rethrows.swift
+++ b/test/SILGen/rethrows.swift
@@ -8,10 +8,10 @@
 func nonthrower() -> Int { return 0 }
 
 // CHECK-LABEL: sil hidden @_T08rethrows5test0yyKF : $@convention(thin) () -> @error Error {
-// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       [[THROWER:%.*]] = function_ref @_T08rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
 // CHECK:       [[T0:%.*]] = thin_to_thick_function [[THROWER]]
 // CHECK:       [[CVT:%.*]] = convert_function [[T0]]
+// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
 // CHECK:     [[NORMAL]]([[T0:%.*]] : $Int):
 // CHECK-NEXT:  [[T1:%.*]] = tuple ()
@@ -23,10 +23,10 @@
 }
 
 // CHECK-LABEL: sil hidden @_T08rethrows5test1yyKF : $@convention(thin) () -> @error Error {
-// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       [[CLOSURE:%.*]] = function_ref @_T08rethrows5test1yyKFSiyKcfU_ : $@convention(thin) () -> (Int, @error Error)
 // CHECK:       [[CVT:%.*]] = convert_function [[CLOSURE]]
 // CHECK:       [[T0:%.*]] = thin_to_thick_function [[CVT]]
+// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       try_apply [[RETHROWER]]([[T0]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
 // CHECK:     [[NORMAL]]([[T0:%.*]] : $Int):
 // CHECK-NEXT:  [[T1:%.*]] = tuple ()
@@ -35,10 +35,10 @@
 // CHECK-NEXT:  throw [[T0]]
 //   Closure.
 // CHECK-LABEL: sil private @_T08rethrows5test1yyKFSiyKcfU_ : $@convention(thin) () -> (Int, @error Error) {
-// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       [[THROWER:%.*]] = function_ref @_T08rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
 // CHECK:       [[T0:%.*]] = thin_to_thick_function [[THROWER]]
 // CHECK:       [[CVT:%.*]] = convert_function [[T0]]
+// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
 // CHECK:     [[NORMAL]]([[T0:%.*]] : $Int):
 // CHECK-NEXT:  return [[T0]]
@@ -49,10 +49,10 @@
 }
 
 // CHECK-LABEL: sil hidden @_T08rethrows5test2yyF : $@convention(thin) () -> () {
-// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       [[NONTHROWER:%.*]] = function_ref @_T08rethrows10nonthrowerSiyF : $@convention(thin) () -> Int
 // CHECK:       [[T0:%.*]] = thin_to_thick_function [[NONTHROWER]]
 // CHECK:       [[T1:%.*]] = convert_function [[T0]] : $@callee_owned () -> Int to $@noescape @callee_owned () -> (Int, @error Error)
+// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       try_apply [[RETHROWER]]([[T1]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
 // CHECK:     [[NORMAL]]([[T0:%.*]] : $Int):
 // CHECK-NEXT:  [[T1:%.*]] = tuple ()
@@ -64,11 +64,11 @@
 }
 
 // CHECK-LABEL: sil hidden @_T08rethrows5test3yyF : $@convention(thin) () -> () {
-// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       [[CLOSURE:%.*]] = function_ref @_T08rethrows5test3yyFSiycfU_ : $@convention(thin) () -> Int
 // CHECK:       [[CVT:%.*]] = convert_function [[CLOSURE]] : $@convention(thin) () -> Int to $@convention(thin) @noescape () -> Int
 // CHECK:       [[T0:%.*]] = thin_to_thick_function [[CVT]]
 // CHECK:       [[T1:%.*]] = convert_function [[T0]] : $@noescape @callee_owned () -> Int to $@noescape @callee_owned () -> (Int, @error Error)
+// CHECK:       [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
 // CHECK:       try_apply [[RETHROWER]]([[T1]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
 // CHECK:     [[NORMAL]]([[T0:%.*]] : $Int):
 // CHECK-NEXT:  [[T1:%.*]] = tuple ()
diff --git a/test/SILGen/scalar_to_tuple_args.swift b/test/SILGen/scalar_to_tuple_args.swift
index 1dbdfd5..14ef601 100644
--- a/test/SILGen/scalar_to_tuple_args.swift
+++ b/test/SILGen/scalar_to_tuple_args.swift
@@ -13,46 +13,45 @@
 
 var x = 0
 // CHECK: [[X_ADDR:%.*]] = global_addr @_T020scalar_to_tuple_args1xSivp : $*Int
-// CHECK: [[INOUT_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args17inoutWithDefaultsySiz_Si1ySi1ztF
 // CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
 // CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[INOUT_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args17inoutWithDefaultsySiz_Si1ySi1ztF
 // CHECK: apply [[INOUT_WITH_DEFAULTS]]([[WRITE]], [[DEFAULT_Y]], [[DEFAULT_Z]])
 inoutWithDefaults(&x)
 
-// CHECK: [[INOUT_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args27inoutWithCallerSideDefaultsySiz_Si1ytF
 // CHECK: [[LINE_VAL:%.*]] = integer_literal
 // CHECK: [[LINE:%.*]] = apply {{.*}}([[LINE_VAL]]
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[INOUT_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args27inoutWithCallerSideDefaultsySiz_Si1ytF
 // CHECK: apply [[INOUT_WITH_CALLER_DEFAULTS]]([[WRITE]], [[LINE]])
 inoutWithCallerSideDefaults(&x)
 
-// CHECK: [[SCALAR_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A12WithDefaultsySi_Si1ySi1ztF
 // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
 // CHECK: [[X:%.*]] = load [trivial] [[READ]]
 // CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
 // CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[SCALAR_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A12WithDefaultsySi_Si1ySi1ztF
 // CHECK: apply [[SCALAR_WITH_DEFAULTS]]([[X]], [[DEFAULT_Y]], [[DEFAULT_Z]])
 scalarWithDefaults(x)
 
-// CHECK: [[SCALAR_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A22WithCallerSideDefaultsySi_Si1ytF
 // CHECK: [[X:%.*]] = load [trivial] [[X_ADDR]]
 // CHECK: [[LINE_VAL:%.*]] = integer_literal
 // CHECK: [[LINE:%.*]] = apply {{.*}}([[LINE_VAL]]
+// CHECK: [[SCALAR_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A22WithCallerSideDefaultsySi_Si1ytF
 // CHECK: apply [[SCALAR_WITH_CALLER_DEFAULTS]]([[X]], [[LINE]])
 scalarWithCallerSideDefaults(x)
 
-// CHECK: [[TUPLE_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0C12WithDefaultsySi_Sit1x_Si1ySi1ztF
 // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
 // CHECK: [[X1:%.*]] = load [trivial] [[READ]]
 // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
 // CHECK: [[X2:%.*]] = load [trivial] [[READ]]
 // CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
 // CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[TUPLE_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0C12WithDefaultsySi_Sit1x_Si1ySi1ztF
 // CHECK: apply [[TUPLE_WITH_DEFAULTS]]([[X1]], [[X2]], [[DEFAULT_Y]], [[DEFAULT_Z]])
 tupleWithDefaults(x: (x,x))
 
-// CHECK: [[VARIADIC_FIRST:%.*]] = function_ref @_T020scalar_to_tuple_args13variadicFirstySid_tF
 // CHECK: [[ALLOC_ARRAY:%.*]] = apply {{.*}} -> (@owned Array<τ_0_0>, Builtin.RawPointer)
 // CHECK: [[BORROWED_ALLOC_ARRAY:%.*]] = begin_borrow [[ALLOC_ARRAY]]
 // CHECK: [[BORROWED_ARRAY:%.*]] = tuple_extract [[BORROWED_ALLOC_ARRAY]] {{.*}}, 0
@@ -64,10 +63,10 @@
 // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
 // CHECK: [[X:%.*]] = load [trivial] [[READ]]
 // CHECK: store [[X]] to [trivial] [[ADDR]]
+// CHECK: [[VARIADIC_FIRST:%.*]] = function_ref @_T020scalar_to_tuple_args13variadicFirstySid_tF
 // CHECK: apply [[VARIADIC_FIRST]]([[ARRAY]])
 variadicFirst(x)
 
-// CHECK: [[VARIADIC_SECOND:%.*]] = function_ref @_T020scalar_to_tuple_args14variadicSecondySi_SidtF
 // CHECK: [[ALLOC_ARRAY:%.*]] = apply {{.*}} -> (@owned Array<τ_0_0>, Builtin.RawPointer)
 // CHECK: [[BORROWED_ALLOC_ARRAY:%.*]] = begin_borrow [[ALLOC_ARRAY]]
 // CHECK: [[BORROWED_ARRAY:%.*]] = tuple_extract [[BORROWED_ALLOC_ARRAY]] {{.*}}, 0
@@ -75,5 +74,6 @@
 // CHECK: end_borrow [[BORROWED_ALLOC_ARRAY]] from [[ALLOC_ARRAY]]
 // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
 // CHECK: [[X:%.*]] = load [trivial] [[READ]]
+// CHECK: [[VARIADIC_SECOND:%.*]] = function_ref @_T020scalar_to_tuple_args14variadicSecondySi_SidtF
 // CHECK: apply [[VARIADIC_SECOND]]([[X]], [[ARRAY]])
 variadicSecond(x)
diff --git a/test/SILGen/shared.swift b/test/SILGen/shared.swift
index ff2fb2e..6b7a27d 100644
--- a/test/SILGen/shared.swift
+++ b/test/SILGen/shared.swift
@@ -7,9 +7,9 @@
 // CHECK-LABEL: sil hidden @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
 func shared_arguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate):
-  // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF
   // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+  // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF
   // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: } // end sil function '_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF'
   return owned_arguments(trivial: trivial, value: value, ref: ref)
@@ -18,9 +18,9 @@
 // CHECK-LABEL: sil hidden @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
 func owned_arguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
-  // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF
   // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+  // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF
   // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]])
   // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
   // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
@@ -55,9 +55,9 @@
 
   // CHECK-LABEL: sil private @_T06shared0A17_argument_captureySih7trivial_AA14ValueAggregateVh5valueAA03RefF0Ch3reftFyycfU_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
-  // CHECK: [[SHARED_CALL:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+  // CHECK: [[SHARED_CALL:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: {{%.*}} = apply [[SHARED_CALL]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
   // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
@@ -69,11 +69,11 @@
   
   // CHECK-LABEL:  sil private @_T06shared0A17_argument_captureySih7trivial_AA14ValueAggregateVh5valueAA03RefF0Ch3reftFyycfU0_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> () {
   // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
-  // CHECK: [[OWNED_CALL:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
   // CHECK: [[COPY_BORROW_VALUE_VAL:%[0-9]+]] = copy_value [[BORROW_VALUE_VAL]] : $ValueAggregate
   // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
   // CHECK: [[COPY_BORROW_REF_VAL:%[0-9]+]] = copy_value [[BORROW_REF_VAL]] : $RefAggregate
+  // CHECK: [[OWNED_CALL:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: {{%.*}} = apply [[OWNED_CALL]]([[TRIVIAL_VAL]], [[COPY_BORROW_VALUE_VAL]], [[COPY_BORROW_REF_VAL]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
   // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
@@ -85,13 +85,13 @@
 // CHECK-LABEL: sil hidden @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
 func shared_to_owned_conversion(_ f : (__shared Int, __shared ValueAggregate, __shared RefAggregate) -> Void) {
   // CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @owned $@noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()):
-  // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: [[OWNED_THUNK:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcFySi_AdFtcfU_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[OWNED_THUNK]]
   // CHECK: [[THICK_OWNED_THUNK:%[0-9]+]] = thin_to_thick_function [[CONVERT]] : $@convention(thin) @noescape (Int, @owned ValueAggregate, @owned RefAggregate) -> () to $@noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: [[GUARANTEED_TO_OWNED_THUNK:%[0-9]+]] =  function_ref @_T0Si6shared14ValueAggregateVAA03RefC0CIxyxx_SiAcEIxygg_TR : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
   // CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [[GUARANTEED_TO_OWNED_THUNK]]([[THICK_OWNED_THUNK]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_THUNK]]
+  // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: destroy_value [[UNUSED_FUNC]] : $@noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: } // end sil function '_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF'
@@ -111,13 +111,13 @@
 // CHECK-LABEL: sil hidden @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
 func owned_to_shared_conversion(_ f : (Int, ValueAggregate, RefAggregate) -> Void) {
   // CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @owned $@noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()):
-  // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
   // CHECK: [[SHARED_THUNK:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcFySih_ADhAFhtcfU_ : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[SHARED_THUNK]]
   // CHECK: [[THICK_SHARED_THUNK:%[0-9]+]] = thin_to_thick_function [[CONVERT]] : $@convention(thin) @noescape (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> () to $@noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
   // CHECK: [[OWNED_TO_GUARANTEED_THUNK:%[0-9]+]] = function_ref @_T0Si6shared14ValueAggregateVAA03RefC0CIxygg_SiAcEIxyxx_TR : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [[OWNED_TO_GUARANTEED_THUNK]]([[THICK_SHARED_THUNK]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
   // CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_THUNK]]
+  // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
   // CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
   // CHECK: destroy_value [[UNUSED_FUNC]] : $@noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
   // CHECK: } // end sil function '_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF'
diff --git a/test/SILGen/source_location.swift b/test/SILGen/source_location.swift
index 8ea33a9..df1405f 100644
--- a/test/SILGen/source_location.swift
+++ b/test/SILGen/source_location.swift
@@ -4,11 +4,11 @@
 
 #sourceLocation(file: "caller.swift", line: 10000)
 _ = printSourceLocation()
-// CHECK: [[PRINT_SOURCE_LOCATION:%.*]] = function_ref @_T015source_location19printSourceLocationySS4file_Si4linetF
 // CHECK: [[CALLER_FILE_VAL:%.*]] = string_literal utf16 "caller.swift",
 // CHECK: [[CALLER_FILE:%.*]] = apply {{.*}}([[CALLER_FILE_VAL]],
 // CHECK: [[CALLER_LINE_VAL:%.*]] = integer_literal $Builtin.Int{{[0-9]+}}, 10000,
 // CHECK: [[CALLER_LINE:%.*]] = apply {{.*}}([[CALLER_LINE_VAL]],
+// CHECK: [[PRINT_SOURCE_LOCATION:%.*]] = function_ref @_T015source_location19printSourceLocationySS4file_Si4linetF
 // CHECK: apply [[PRINT_SOURCE_LOCATION]]([[CALLER_FILE]], [[CALLER_LINE]])
 
 #sourceLocation(file: "inplace.swift", line: 20000)
diff --git a/test/SILGen/statements.swift b/test/SILGen/statements.swift
index 82f573d..464bec8 100644
--- a/test/SILGen/statements.swift
+++ b/test/SILGen/statements.swift
@@ -164,9 +164,9 @@
 // CHECK-LABEL: sil hidden @{{.*}}for_loops2
 func for_loops2() {
   // rdar://problem/19316670
-  // CHECK: [[NEXT:%[0-9]+]] = function_ref @_T0s16IndexingIteratorV4next{{[_0-9a-zA-Z]*}}F
-  // CHECK-NEXT: alloc_stack $Optional<MyClass>
+  // CHECK: alloc_stack $Optional<MyClass>
   // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown]
+  // CHECK: [[NEXT:%[0-9]+]] = function_ref @_T0s16IndexingIteratorV4next{{[_0-9a-zA-Z]*}}F
   // CHECK-NEXT: apply [[NEXT]]<[MyClass]>
   // CHECK: class_method [[OBJ:%[0-9]+]] : $MyClass, #MyClass.foo!1
   let objects = [MyClass(), MyClass() ]
@@ -365,8 +365,8 @@
 
 // CHECK-LABEL: sil hidden @_T010statements7test_doyyF
 func test_do() {
-  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: integer_literal $Builtin.Int2048, 0
+  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: apply [[BAR]](
   bar(0)
   // CHECK-NOT: br bb
@@ -376,8 +376,8 @@
     let obj = MyClass()
     _ = obj
     
-    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: integer_literal $Builtin.Int2048, 1
+    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: apply [[BAR]](
     bar(1)
 
@@ -386,16 +386,16 @@
     // CHECK-NOT: br bb
   }
 
-  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: integer_literal $Builtin.Int2048, 2
+  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: apply [[BAR]](
   bar(2)
 }
 
 // CHECK-LABEL: sil hidden @_T010statements15test_do_labeledyyF
 func test_do_labeled() {
-  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: integer_literal $Builtin.Int2048, 0
+  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: apply [[BAR]](
   bar(0)
   // CHECK: br bb1
@@ -406,8 +406,8 @@
     let obj = MyClass()
     _ = obj
 
-    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: integer_literal $Builtin.Int2048, 1
+    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: apply [[BAR]](
     bar(1)
 
@@ -421,8 +421,8 @@
     }
 
     // CHECK: bb3:
-    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: integer_literal $Builtin.Int2048, 2
+    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: apply [[BAR]](
     bar(2)
 
@@ -436,8 +436,8 @@
     }
 
     // CHECK: bb5:
-    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: integer_literal $Builtin.Int2048, 3
+    // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
     // CHECK: apply [[BAR]](
     bar(3)
 
@@ -445,8 +445,8 @@
     // CHECK: br bb6
   }
 
-  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: integer_literal $Builtin.Int2048, 4
+  // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
   // CHECK: apply [[BAR]](
   bar(4)
 }
diff --git a/test/SILGen/struct_resilience.swift b/test/SILGen/struct_resilience.swift
index ce8a8c9..5877d84 100644
--- a/test/SILGen/struct_resilience.swift
+++ b/test/SILGen/struct_resilience.swift
@@ -16,11 +16,11 @@
 // CHECK:         copy_addr %1 to [initialization] [[OTHER_SIZE_BOX:%[0-9]*]] : $*Size
   var s2 = s
 
-// CHECK:         [[SETTER:%.*]] = function_ref @_T016resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> ()
 // CHECK:         copy_addr %1 to [initialization] [[SIZE_BOX:%.*]] : $*Size
 // CHECK:         [[GETTER:%.*]] = function_ref @_T016resilient_struct4SizeV1wSivg : $@convention(method) (@in_guaranteed Size) -> Int
 // CHECK:         [[RESULT:%.*]] = apply [[GETTER]]([[SIZE_BOX]])
 // CHECK:         [[WRITE:%.*]] = begin_access [modify] [unknown] [[OTHER_SIZE_BOX]] : $*Size
+// CHECK:         [[SETTER:%.*]] = function_ref @_T016resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> ()
 // CHECK:         apply [[SETTER]]([[RESULT]], [[WRITE]])
   s2.w = s.w
 
@@ -39,14 +39,14 @@
 // Use materializeForSet for inout access of properties in resilient structs
 // from a different resilience domain
 
-func inoutFunc(_ x: inout Int) {}
+public func inoutFunc(_ x: inout Int) {}
 
 // CHECK-LABEL: sil hidden @_T017struct_resilience18resilientInOutTesty0c1_A04SizeVzF : $@convention(thin) (@inout Size) -> ()
 
 func resilientInOutTest(_ s: inout Size) {
 
-// CHECK:         function_ref @_T017struct_resilience9inoutFuncySizF
 // CHECK:         function_ref @_T016resilient_struct4SizeV1wSivm
+// CHECK:         function_ref @_T017struct_resilience9inoutFuncySizF
 
   inoutFunc(&s.w)
 
@@ -255,11 +255,26 @@
 @_versioned
 @_transparent func useVersionedResilientStruct(_ s: VersionedResilientStruct)
     -> VersionedResilientStruct {
-  // CHECK:       function_ref @_T017struct_resilience24VersionedResilientStructVACSi1x_Si1ytcfC
   // CHECK:       function_ref @_T017struct_resilience24VersionedResilientStructV1ySivg
   // CHECK:       function_ref @_T017struct_resilience24VersionedResilientStructV1xSivg
+  // CHECK:       function_ref @_T017struct_resilience24VersionedResilientStructVACSi1x_Si1ytcfC
 
   return VersionedResilientStruct(x: s.y, y: s.x)
+
+  // CHECK:       return
+}
+
+// CHECK-LABEL: sil [serialized] @_T017struct_resilience19inlineableInoutTestyAA6MySizeVzF : $@convention(thin) (@inout MySize) -> ()
+@_inlineable public func inlineableInoutTest(_ s: inout MySize) {
+  // Inlineable functions can be inlined in other resiliene domains.
+  //
+  // Make sure we use materializeForSet for an inout access of a resilient struct
+  // property inside an inlinable function.
+
+  // CHECK:       function_ref @_T017struct_resilience6MySizeV1wSivm
+  inoutFunc(&s.w)
+
+  // CHECK:       return
 }
 
 // Initializers for resilient structs
diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift
index f37e55b..b7126bd 100644
--- a/test/SILGen/subclass_existentials.swift
+++ b/test/SILGen/subclass_existentials.swift
@@ -126,8 +126,7 @@
   // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[BORROW]] : $Base<Int> & P to $@opened("{{.*}}") Base<Int> & P
   // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] : $@opened("{{.*}}") Base<Int> & P
   // CHECK: [[CLASS_REF:%.*]] = upcast [[REF]] : $@opened("{{.*}}") Base<Int> & P to $Base<Int>
-  // CHECK: [[BORROWED_CLASS_REF:%.*]] = begin_borrow [[CLASS_REF]]
-  // CHECK: [[METHOD:%.*]] = class_method [[BORROWED_CLASS_REF]] : $Base<Int>, #Base.classSelfReturn!1 : <T> (Base<T>) -> () -> @dynamic_self Base<T>, $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0>
+  // CHECK: [[METHOD:%.*]] = class_method [[CLASS_REF]] : $Base<Int>, #Base.classSelfReturn!1 : <T> (Base<T>) -> () -> @dynamic_self Base<T>, $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0>
   // CHECK: [[RESULT_CLASS_REF:%.*]] = apply [[METHOD]]<Int>([[CLASS_REF]]) : $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0>
   // CHECK: destroy_value [[CLASS_REF]] : $Base<Int>
   // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_CLASS_REF]] : $Base<Int> to $@opened("{{.*}}") Base<Int> & P
@@ -138,10 +137,10 @@
 
   // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Base<Int> & P
   // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[BORROW]] : $Base<Int> & P to $@opened("{{.*}}") Base<Int> & P
-  // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") Base<Int> & P, #P.protocolSelfReturn!1 : <Self where Self : P> (Self) -> () -> @dynamic_self Self, [[PAYLOAD]] : $@opened("{{.*}}") Base<Int> & P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK: [[RESULT_BOX:%.*]] = alloc_stack $@opened("{{.*}}") Base<Int> & P
   // CHECK: [[SELF_BOX:%.*]] = alloc_stack $@opened("{{.*}}") Base<Int> & P
   // CHECK: store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}") Base<Int> & P
+  // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") Base<Int> & P, #P.protocolSelfReturn!1 : <Self where Self : P> (Self) -> () -> @dynamic_self Self, [[PAYLOAD]] : $@opened("{{.*}}") Base<Int> & P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK: apply [[METHOD]]<@opened("{{.*}}") Base<Int> & P>([[RESULT_BOX]], [[SELF_BOX]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
   // CHECK: dealloc_stack [[SELF_BOX]] : $*@opened("{{.*}}") Base<Int> & P
   // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BOX]] : $*@opened("{{.*}}") Base<Int> & P
@@ -152,8 +151,8 @@
   let _: Base<Int> & P = baseAndP.protocolSelfReturn()
 
   // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
-  // CHECK: [[METHOD:%.*]] = function_ref @_T021subclass_existentials4BaseC15classSelfReturnACyxGXDyFZ : $@convention(method) <τ_0_0> (@thick Base<τ_0_0>.Type) -> @owned Base<τ_0_0>
   // CHECK: [[METATYPE_REF:%.*]] = upcast [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type to $@thick Base<Int>.Type
+  // CHECK: [[METHOD:%.*]] = function_ref @_T021subclass_existentials4BaseC15classSelfReturnACyxGXDyFZ : $@convention(method) <τ_0_0> (@thick Base<τ_0_0>.Type) -> @owned Base<τ_0_0>
   // CHECK: [[RESULT_REF2:%.*]] = apply [[METHOD]]<Int>([[METATYPE_REF]])
   // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_REF2]] : $Base<Int> to $@opened("{{.*}}") (Base<Int> & P)
   // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") (Base<Int> & P) : $@opened("{{.*}}") (Base<Int> & P), $Base<Int> & P
@@ -161,8 +160,8 @@
   let _: Base<Int> & P = baseAndPType.classSelfReturn()
 
   // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
-  // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") (Base<Int> & P), #P.protocolSelfReturn!1 : <Self where Self : P> (Self.Type) -> () -> @dynamic_self Self, [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
   // CHECK: [[RESULT:%.*]] = alloc_stack $@opened("{{.*}}") (Base<Int> & P)
+  // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") (Base<Int> & P), #P.protocolSelfReturn!1 : <Self where Self : P> (Self.Type) -> () -> @dynamic_self Self, [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
   // CHECK: apply [[METHOD]]<@opened("{{.*}}") (Base<Int> & P)>([[RESULT]], [[METATYPE]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
   // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT]] : $*@opened("{{.*}}") (Base<Int> & P)
   // CHECK: [[RESULT_VALUE:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") (Base<Int> & P) : $@opened("{{.*}}") (Base<Int> & P), $Base<Int> & P
diff --git a/test/SILGen/super_init_refcounting.swift b/test/SILGen/super_init_refcounting.swift
index ab154d6..2809ebf 100644
--- a/test/SILGen/super_init_refcounting.swift
+++ b/test/SILGen/super_init_refcounting.swift
@@ -84,13 +84,13 @@
   // CHECK:         assign {{.*}} to [[WRITE]] : $*Int
   // CHECK:         [[SELF_OBJ:%.*]] = load [take] [[PB_SELF_BOX]] : $*Good
   // CHECK:         [[SUPER_OBJ:%.*]] = upcast [[SELF_OBJ]] : $Good to $Foo
-  // CHECK:         [[SUPER_INIT:%.*]] = function_ref @_T022super_init_refcounting3FooCACSicfc : $@convention(method) (Int, @owned Foo) -> @owned Foo
   // CHECK:         [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER_OBJ]]
   // CHECK:         [[DOWNCAST_BORROWED_SUPER:%.*]] = unchecked_ref_cast [[BORROWED_SUPER]] : $Foo to $Good
   // CHECK:         [[X_ADDR:%.*]] = ref_element_addr [[DOWNCAST_BORROWED_SUPER]] : $Good, #Good.x
   // CHECK:         [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
   // CHECK:         [[X:%.*]] = load [trivial] [[READ]] : $*Int
   // CHECK:         end_borrow [[BORROWED_SUPER]] from [[SUPER_OBJ]]
+  // CHECK:         [[SUPER_INIT:%.*]] = function_ref @_T022super_init_refcounting3FooCACSicfc : $@convention(method) (Int, @owned Foo) -> @owned Foo
   // CHECK:         apply [[SUPER_INIT]]([[X]], [[SUPER_OBJ]])
   override init() {
     x = 10
diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift
index 342c633..cff6657 100644
--- a/test/SILGen/switch_var.swift
+++ b/test/SILGen/switch_var.swift
@@ -50,9 +50,9 @@
   // CHECK:   [[X:%.*]] = project_box [[XADDR]]
   // CHECK-NOT: br bb
   case var x:
-  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   destroy_value [[XADDR]]
   // CHECK:   br [[CONT:bb[0-9]+]]
     a(x: x)
@@ -68,31 +68,31 @@
   switch foo() {
   // CHECK:   [[XADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[X:%.*]] = project_box [[XADDR]]
-  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
   // -- TODO: Clean up these empty waypoint bbs.
   case var x where runced(x: x):
   // CHECK: [[CASE1]]:
-  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   destroy_value [[XADDR]]
   // CHECK:   br [[CONT:bb[0-9]+]]
     a(x: x)
   // CHECK: [[NO_CASE1]]:
   // CHECK:   [[YADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[Y:%.*]] = project_box [[YADDR]]
-  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
   case var y where funged(x: y):
   // CHECK: [[CASE2]]:
-  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
   // CHECK:   destroy_value [[YADDR]]
   // CHECK:   br [[CONT]]
     b(x: y)
@@ -102,9 +102,9 @@
   // CHECK: [[CASE3]]:
   // CHECK:   [[ZADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[Z:%.*]] = project_box [[ZADDR]]
-  // CHECK:   function_ref @_T010switch_var1cySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1cySi1x_tF
   // CHECK:   destroy_value [[ZADDR]]
   // CHECK:   br [[CONT]]
     c(x: z)
@@ -121,15 +121,15 @@
   switch (foo(), bar()) {
   // CHECK:   [[XADDR:%.*]] = alloc_box ${ var (Int, Int) }
   // CHECK:   [[X:%.*]] = project_box [[XADDR]]
-  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   tuple_element_addr [[READ]] : {{.*}}, 0
+  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
   case var x where runced(x: x.0):
   // CHECK: [[CASE1]]:
-  // CHECK:   function_ref @_T010switch_var2aaySi_Sit1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var2aaySi_Sit1x_tF
   // CHECK:   destroy_value [[XADDR]]
   // CHECK:   br [[CONT:bb[0-9]+]]
     aa(x: x)
@@ -141,18 +141,18 @@
   // CHECK:   [[Y:%.*]] = project_box [[YADDR]]
   // CHECK:   [[ZADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[Z:%.*]] = project_box [[ZADDR]]
-  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
   case (var y, var z) where funged(x: y):
   // CHECK: [[CASE2]]:
-  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
-  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
+  // CHECK:   function_ref @_T010switch_var1aySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
   // CHECK:   destroy_value [[ZADDR]]
   // CHECK:   destroy_value [[YADDR]]
   // CHECK:   br [[CONT]]
@@ -161,15 +161,15 @@
   // CHECK: [[NO_CASE2]]:
   // CHECK:   [[WADDR:%.*]] = alloc_box ${ var (Int, Int) }
   // CHECK:   [[W:%.*]] = project_box [[WADDR]]
-  // CHECK:   function_ref @_T010switch_var5ansedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[W]]
   // CHECK:   tuple_element_addr [[READ]] : {{.*}}, 0
+  // CHECK:   function_ref @_T010switch_var5ansedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
   case var w where ansed(x: w.0):
   // CHECK: [[CASE3]]:
-  // CHECK:   function_ref @_T010switch_var2bbySi_Sit1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[W]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var2bbySi_Sit1x_tF
   // CHECK:   br [[CONT]]
     bb(x: w)
   // CHECK: [[NO_CASE3]]:
@@ -179,9 +179,9 @@
   // CHECK: [[CASE4]]:
   // CHECK:   [[VADDR:%.*]] = alloc_box ${ var (Int, Int) } 
   // CHECK:   [[V:%.*]] = project_box [[VADDR]]
-  // CHECK:   function_ref @_T010switch_var2ccySi_Sit1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[V]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var2ccySi_Sit1x_tF
   // CHECK:   destroy_value [[VADDR]]
   // CHECK:   br [[CONT]]
     cc(x: v)
@@ -214,9 +214,9 @@
   // CHECK:   [[XADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[X:%.*]] = project_box [[XADDR]]
   // CHECK:   store [[PAIR_1]] to [trivial] [[X]]
-  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[X]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var6runcedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
   case (is X, var x) where runced(x: x):
   // CHECK: [[CASE1]]:
@@ -245,16 +245,16 @@
   // CHECK:   [[YADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[Y:%.*]] = project_box [[YADDR]]
   // CHECK:   store [[PAIR_1]] to [trivial] [[Y]]
-  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var6fungedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
 
   case (is Y, var y) where funged(x: y):
   // CHECK: [[CASE2]]:
-  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1bySi1x_tF
   // CHECK:   destroy_value [[YADDR]]
   // CHECK:   dealloc_stack [[TMP]]
   // CHECK:   destroy_addr [[PAIR_0]] : $*P
@@ -273,15 +273,15 @@
   // CHECK: [[NEXT]]:
   // CHECK:   [[ZADDR:%.*]] = alloc_box ${ var (P, Int) }
   // CHECK:   [[Z:%.*]] = project_box [[ZADDR]]
-  // CHECK:   function_ref @_T010switch_var5ansedSbSi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
   // CHECK:   tuple_element_addr [[READ]] : {{.*}}, 1
+  // CHECK:   function_ref @_T010switch_var5ansedSbSi1x_tF
   // CHECK:   cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[DFLT_NO_CASE3:bb[0-9]+]]
   case var z where ansed(x: z.1):
   // CHECK: [[CASE3]]:
-  // CHECK:   function_ref @_T010switch_var1cySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
   // CHECK:   tuple_element_addr [[READ]] : {{.*}}, 1
+  // CHECK:   function_ref @_T010switch_var1cySi1x_tF
   // CHECK:   destroy_value [[ZADDR]]
   // CHECK-NEXT: dealloc_stack [[PAIR]]
   // CHECK:   br [[CONT]]
@@ -295,9 +295,9 @@
   // CHECK:   [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0
   // CHECK:   [[WADDR:%.*]] = alloc_box ${ var Int }
   // CHECK:   [[W:%.*]] = project_box [[WADDR]]
-  // CHECK:   function_ref @_T010switch_var1dySi1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[W]]
   // CHECK:   load [trivial] [[READ]]
+  // CHECK:   function_ref @_T010switch_var1dySi1x_tF
   // CHECK:   destroy_value [[WADDR]]
   // CHECK:   destroy_addr [[PAIR_0]] : $*P
   // CHECK:   dealloc_stack [[PAIR]]
@@ -407,9 +407,9 @@
   switch foos() {
   case let x where runced():
   // CHECK: [[CASE1]]:
-  // CHECK:   [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
   // CHECK:   [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
   // CHECK:   [[VAL_COPY_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY]]
+  // CHECK:   [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
   // CHECK:   apply [[A]]([[VAL_COPY_COPY]])
   // CHECK:   end_borrow [[BORROWED_VAL_COPY]] from [[VAL_COPY]]
   // CHECK:   destroy_value [[VAL_COPY]]
@@ -425,9 +425,9 @@
   // CHECK:   cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
   case let y where funged():
   // CHECK: [[CASE2]]:
-  // CHECK:   [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
   // CHECK:   [[BORROWED_VAL_COPY_2:%.*]] = begin_borrow [[VAL_COPY_2]]
   // CHECK:   [[VAL_COPY_2_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY_2]]
+  // CHECK:   [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
   // CHECK:   apply [[B]]([[VAL_COPY_2_COPY]])
   // CHECK:   end_borrow [[BORROWED_VAL_COPY_2]] from [[VAL_COPY_2]]
   // CHECK:   destroy_value [[VAL_COPY_2]]
@@ -486,9 +486,9 @@
   // CHECK:   cond_br {{.*}}, [[CASE1:bb[0-9]+]], [[NOCASE1:bb[0-9]+]]
   case var x where runced():
   // CHECK: [[CASE1]]:
-  // CHECK:   [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
   // CHECK:   [[READ:%.*]] = begin_access [read] [unknown] [[PBOX]]
   // CHECK:   [[X:%.*]] = load [copy] [[READ]]
+  // CHECK:   [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
   // CHECK:   apply [[A]]([[X]])
   // CHECK:   destroy_value [[BOX]]
   // CHECK:   br [[CONT:bb[0-9]+]]
@@ -504,9 +504,9 @@
   case let y where funged():
 
   // CHECK: [[CASE2]]:
-  // CHECK:   [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
   // CHECK:   [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
   // CHECK:   [[VAL_COPY_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY]]
+  // CHECK:   [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
   // CHECK:   apply [[B]]([[VAL_COPY_COPY]])
   // CHECK:   end_borrow [[BORROWED_VAL_COPY]] from [[VAL_COPY]]
   // CHECK:   destroy_value [[VAL_COPY]]
@@ -721,8 +721,8 @@
     
     // CHECK:   [[CASE_BODY]]([[BODY_X:%.*]] : $Int):
     // CHECK:     store [[BODY_X]] to [trivial] [[BOX_X:%.*]] : $*Int
-    // CHECK:     [[FUNC_AAA:%.*]] = function_ref @_T010switch_var3aaaySiz1x_tF
     // CHECK:     [[WRITE:%.*]] = begin_access [modify] [unknown] [[BOX_X]]
+    // CHECK:     [[FUNC_AAA:%.*]] = function_ref @_T010switch_var3aaaySiz1x_tF
     // CHECK:     apply [[FUNC_AAA]]([[WRITE]])
     aaa(x: &x)
   }
diff --git a/test/SILGen/transparent_attribute.swift b/test/SILGen/transparent_attribute.swift
index 8174a77..f0a72fd 100644
--- a/test/SILGen/transparent_attribute.swift
+++ b/test/SILGen/transparent_attribute.swift
@@ -1,212 +1,14 @@
 // RUN: %target-swift-frontend -emit-silgen -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
 
 // Test that the attribute gets set on default argument generators.
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tFfA_ : $@convention(thin) () -> Int {
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tF : $@convention(thin) (Int) -> Int {
+
 @_transparent func transparentFuncWithDefaultArgument (x: Int = 1) -> Int {
   return x
 }
 func useTransparentFuncWithDefaultArgument() -> Int {
-  return transparentFuncWithDefaultArgument();
-
-  // CHECK-LABEL: sil hidden @_T021transparent_attribute37useTransparentFuncWithDefaultArgumentSiyF
-  // CHECK: apply {{.*}} line:8:44
-  // CHECK: apply {{.*}} line:8:10
-  // CHECK: return
-  
-}
-
-func transparentFuncWithoutDefaultArgument (x: Int = 1) -> Int {
-  return x
-}
-func useTransparentFuncWithoutDefaultArgument() -> Int {
-  return transparentFuncWithoutDefaultArgument();
-
-  // CHECK-LABEL: sil hidden @_T021transparent_attribute40useTransparentFuncWithoutDefaultArgumentSiyF
-  // CHECK: apply {{.*}} line:21:47
-  // CHECK-NOT: transparent
-  // CHECK: apply {{.*}} line:21:10
-  // CHECK: return
-  
-}
-
-// Make sure the transparent attribute is set on constructors (allocating and initializing).
-struct StructWithTranspConstructor {
-  @_transparent init () {}
-}
-func testStructWithTranspConstructor() -> StructWithTranspConstructor {
-  return StructWithTranspConstructor()
-  
-  // transparent_attribute.StructWithTranspConstructor.constructor
-  // CHECK-APPLY: sil hidden @_T021transparent_attribute27StructWithTranspConstructorV{{[_0-9a-zA-Z]*}}fC
-  
-  // testStructWithTranspConstructor
-  // CHECK-APPLY: _T21transparent_attribute31testStructWithTranspConstructorFT_VS_27StructWithTranspConstructor
-  // CHECK: apply {{.*}} line:36:10
-  
-}
-
-struct MySt {}
-var _x = MySt()
-var x1 : MySt {
-  @_transparent
-  get {
-    return _x
-  }
-  @_transparent
-  set {
-    _x = newValue
-  }
-}
-var x2 : MySt {
-  @_transparent
-  set(v) {
-    _x = v
-  }
-  @_transparent
-  get {
-    return _x
-  }
-}
-func testProperty(z: MySt) {
-  x1 = z
-  x2 = z
-  var m1 : MySt = x1
-  var m2 : MySt = x2
-  // CHECK-APPLY: sil hidden @_T021transparent_attribute12testPropertyyAA4MyStV1z_tF
-  // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvs
-  // CHECK-NEXT: apply
-  // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvs
-  // CHECK-NEXT: apply
-  // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvg
-  // CHECK-NEXT: apply
-  // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvg
-  // CHECK-NEXT: apply
-}
-
-var _tr2 = MySt()
-var _tr3 = MySt()
-struct MyTranspStruct {}
-extension MyTranspStruct {
-  @_transparent
-  init(input : MySt) {}
-  mutating
-  func tr1() {}
-  var tr2: MySt {
-    get {
-      return _tr2
-    }
-    set {
-      _tr2 = newValue
-    }
-  }
-}
-
-extension MyTranspStruct {
-    @_transparent
-    var tr3: MySt {
-    get {
-      return _tr3
-    }
-    set {
-      _tr3 = newValue
-    }
-  }
-}
-
-func testStructExtension() {
-  var c : MyTranspStruct = MyTranspStruct(input: _x)
-  c.tr1()
-  var s : MySt = c.tr2
-  var t : MySt = c.tr3
-  // CHECK-APPLY: sil hidden @_TF21transparent_attribute13testStructExtensionFT_T_
-  // CHECK: [[INIT:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV{{[_0-9a-zA-Z]*}}fC
-  // CHECK: apply [[INIT]]
-  // CHECK: [[TR1:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr1{{[_0-9a-zA-Z]*}}F
-  // CHECK: apply [[TR1]]
-  // CHECK: [[TR2:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr2AA0C2StVvg
-  // CHECK: apply [[TR2]]
-  // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr3AA0C2StVvg
-  // CHECK: apply [[TR3]]
-}
-
-enum MyEnum {
-  case onetransp
-  case twotransp
-}
-
-extension MyEnum {
-  @_transparent
-  func tr3() {}
-}
-
-func testEnumExtension() {
-  MyEnum.onetransp.tr3()
-  // CHECK-APPLY: sil hidden @_T021transparent_attribute17testEnumExtensionyyF
-  // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute6MyEnumO3tr3{{[_0-9a-zA-Z]*}}F
-  // CHECK: [[INIT:%[0-9]+]] = enum $MyEnum, #MyEnum.onetransp!enumelt
-  // CHECK: apply [[TR3]]([[INIT]])
-}
-
-struct testVarDecl {
-  @_transparent var max: Int {
-    get {
-      return 0xFF
-    }
-    mutating
-    set {
-      max = 0xFF
-    }
-  }
-  func testVarDeclFoo () {
-    var z: Int = max
-    // CHECK-APPLY: sil hidden @_T021transparent_attribute11testVarDeclV0cdE3Foo{{[_0-9a-zA-Z]*}}F
-    // CHECK: [[TR4:%[0-9]+]] = function_ref @_T021transparent_attribute11testVarDeclV3maxSivg
-    // CHECK: apply [[TR4]]
-  }
-}
-
-struct testVarDeclShortenedSyntax {
-  @_transparent static var max: Int { return 0xFF };
-  func testVarDeclShortenedSyntaxfoo () {
-    var z: Int = testVarDeclShortenedSyntax.max
-    // CHECK-APPLY: sil hidden @_T021transparent_attribute26testVarDeclShortenedSyntaxV0cdeF9Syntaxfoo{{[_0-9a-zA-Z]*}}F
-    // CHECK: [[TR5:%[0-9]+]] = function_ref @_T021transparent_attribute26testVarDeclShortenedSyntaxV3maxSivgZ
-    // CHECK: apply [[TR5]]
-  }
-};
-
-@_transparent var transparentOnGlobalVar: Int {
-  get {
-    return 0xFF
-  }
-}
-// CHECK: sil hidden [transparent] @_T021transparent_attribute0A11OnGlobalVarSivg
-
-// Local functions in transparent context are fragile.
-@_transparent public func foo() {
-  // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3barL_yyF : $@convention(thin) () -> ()
-  func bar() {}
-  bar()
-
-  // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyFyycfU_ : $@convention(thin) () -> () {
-  let f: () -> () = {}
-  f()
-
-  // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF : $@convention(thin) () -> () {
-  func zim() {
-    // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF4zangL_yyF : $@convention(thin) () -> () {
-    func zang() {
-    }
-    zang()
-  }
-  zim()
-}
-
-
-// Check that @_versioned entities have public linkage.
-// CHECK-LABEL: sil @_T021transparent_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
-@_versioned func referencedFromTransparent() {}
-
-// CHECK-LABEL: sil [transparent] [serialized] @_T021transparent_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
-@_transparent public func referencesVersionedFunc() -> () -> () {
-  return referencedFromTransparent
+  return transparentFuncWithDefaultArgument()
 }
diff --git a/test/SILGen/tsan_instrumentation.swift b/test/SILGen/tsan_instrumentation.swift
index 2bf6ec0..070cc9d 100644
--- a/test/SILGen/tsan_instrumentation.swift
+++ b/test/SILGen/tsan_instrumentation.swift
@@ -18,9 +18,9 @@
 
 // CHECK-LABEL: sil hidden @_T020tsan_instrumentation17inoutGlobalStructyyF : $@convention(thin) () -> () {
 // CHECK:  [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation7gStructAA02MyC0Vvp : $*MyStruct
-// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutyAA8MyStructVzF : $@convention(thin) (@inout MyStruct) -> ()
 // CHECK:  [[WRITE:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]] : $*MyStruct
 // CHECK:  {{%.*}} = builtin "tsanInoutAccess"([[WRITE]] : $*MyStruct) : $()
+// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutyAA8MyStructVzF : $@convention(thin) (@inout MyStruct) -> ()
 // CHECK:  {{%.*}} = apply [[TAKES_INOUT_FUNC]]([[WRITE]]) : $@convention(thin) (@inout MyStruct) -> ()
 func inoutGlobalStruct() {
   takesInout(&gStruct)
@@ -29,11 +29,11 @@
 
 // CHECK-LABEL: sil hidden @_T020tsan_instrumentation31inoutGlobalStructStoredPropertyyyF : $@convention(thin) () -> () {
 // CHECK:  [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation7gStructAA02MyC0Vvp : $*MyStruct
-// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
 // CHECK:  [[WRITE:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]] : $*MyStruct
 // CHECK:  {{%.*}} = builtin "tsanInoutAccess"([[WRITE]] : $*MyStruct) : $()
 // CHECK:  [[ELEMENT_ADDR:%.*]] = struct_element_addr [[WRITE]] : $*MyStruct, #MyStruct.storedProperty
 // CHECK:  {{%.*}} = builtin "tsanInoutAccess"([[ELEMENT_ADDR]] : $*Int) : $()
+// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
 // CHECK:  {{%.*}} = apply [[TAKES_INOUT_FUNC]]([[ELEMENT_ADDR]]) : $@convention(thin) (@inout Int) -> ()
 func inoutGlobalStructStoredProperty() {
   // This should generate two TSan inout instrumentations; one for the address
@@ -43,15 +43,14 @@
 
 // CHECK-LABEL: sil hidden @_T020tsan_instrumentation30inoutGlobalClassStoredPropertyyyF : $@convention(thin) () -> () {
 // CHECK:  [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation6gClassAA02MyC0Cvp : $*MyClass
-// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
 // CHECK:  [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]] : $*MyClass
 // CHECK:  [[LOADED_CLASS:%.*]] = load [copy] [[READ]] : $*MyClass
 // CHECK:  [[VALUE_BUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
 // CHECK:  [[TEMPORARY:%.*]] = alloc_stack $Int
 // CHECK:  [[BORROWED_CLASS:%.*]] = begin_borrow [[LOADED_CLASS]] : $MyClass
 // CHECK:  [[TEMPORARY_RAW:%.*]] = address_to_pointer [[TEMPORARY]] : $*Int to $Builtin.RawPointer
-// CHECK:  [[MATERIALIZE_FOR_SET:%.*]] = class_method [[BORROWED_CLASS]] : $MyClass, #MyClass.storedProperty!materializeForSet.1 : (MyClass) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?), $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
 // CHECK:  {{%.*}} = builtin "tsanInoutAccess"([[VALUE_BUFFER]] : $*Builtin.UnsafeValueBuffer) : $()
+// CHECK:  [[MATERIALIZE_FOR_SET:%.*]] = class_method [[BORROWED_CLASS]] : $MyClass, #MyClass.storedProperty!materializeForSet.1 : (MyClass) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?), $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
 // CHECK:  [[MATERIALIZE_FOR_SET_TUPLE:%.*]] = apply [[MATERIALIZE_FOR_SET]]([[TEMPORARY_RAW]], [[VALUE_BUFFER]], [[BORROWED_CLASS]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
 // CHECK:  [[TEMPORARY_BUFFER:%.*]] = tuple_extract [[MATERIALIZE_FOR_SET_TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
 // CHECK:  [[OPTIONAL_CALLBACK:%.*]] = tuple_extract [[MATERIALIZE_FOR_SET_TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 1
@@ -59,6 +58,7 @@
 // CHECK:  [[BUFFER_ADDRESS_DEPENDENCE:%.*]] = mark_dependence [[BUFFER_ADDRESS]] : $*Int on [[LOADED_CLASS]] : $MyClass
 // CHECK:  end_borrow [[BORROWED_CLASS]] from [[LOADED_CLASS]] : $MyClass, $MyClass
 // CHECK:  {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_DEPENDENCE]] : $*Int) : $()
+// CHECK:  [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
 // CHECK:  {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_DEPENDENCE]]) : $@convention(thin) (@inout Int) -> ()
 func inoutGlobalClassStoredProperty() {
   // This generates two TSan inout instrumentations. One for the value
diff --git a/test/SILGen/tuples.swift b/test/SILGen/tuples.swift
index 3d7d9d3..349690d 100644
--- a/test/SILGen/tuples.swift
+++ b/test/SILGen/tuples.swift
@@ -43,9 +43,9 @@
   // CHECK-NEXT: store [[T1]] to [trivial] [[PAIR_1]]
   var pair : (y:P, x:Int) = make_xy()
 
+  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[T0:%.*]] = function_ref @_T06tuples7make_xySi1x_AA1P_p1ytyF
-  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
   // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[TEMP]])
   // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int)
   // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0
@@ -90,9 +90,9 @@
   // CHECK-NEXT: // function_ref
   // CHECK:      [[T0:%.*]] = function_ref @_T06tuples8make_intSiyF
   // CHECK-NEXT: [[INT:%.*]] = apply [[T0]]()
+  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
   // CHECK-NEXT: // function_ref
   // CHECK-NEXT: [[T0:%.*]] = function_ref @_T06tuples6make_pAA1P_pyF 
-  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
   // CHECK-NEXT: apply [[T0]]([[TEMP]])
   // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int)
   // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0
diff --git a/test/SILGen/unowned.swift b/test/SILGen/unowned.swift
index 6d8b9a8..68a045f 100644
--- a/test/SILGen/unowned.swift
+++ b/test/SILGen/unowned.swift
@@ -122,8 +122,6 @@
 // CHECK-NEXT:   [[UNOWNED_ARG:%.*]] = copy_unowned_value [[ARG]] : $@sil_unowned C
 // CHECK-NEXT:   [[BORROWED_UNOWNED_ARG:%.*]] = begin_borrow [[UNOWNED_ARG]]
 // CHECK-NEXT:   [[FUN:%.*]] = class_method [[BORROWED_UNOWNED_ARG]] : $C, #C.f!1 : (C) -> () -> Int, $@convention(method) (@guaranteed C) -> Int
-// CHECK-NEXT:   end_borrow [[BORROWED_UNOWNED_ARG]]
-// CHECK-NEXT:   [[BORROWED_UNOWNED_ARG:%.*]] = begin_borrow [[UNOWNED_ARG]]
 // CHECK-NEXT:   [[RESULT:%.*]] = apply [[FUN]]([[BORROWED_UNOWNED_ARG]]) : $@convention(method) (@guaranteed C) -> Int
 // CHECK-NEXT:   end_borrow [[BORROWED_UNOWNED_ARG]]
 // CHECK-NEXT:   destroy_value [[UNOWNED_ARG]]
diff --git a/test/SILGen/versioned_attribute.swift b/test/SILGen/versioned_attribute.swift
index 5a01525..b544b48 100644
--- a/test/SILGen/versioned_attribute.swift
+++ b/test/SILGen/versioned_attribute.swift
@@ -1,5 +1,14 @@
 // RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
 
+// Check that @_versioned entities have public linkage.
+// CHECK-LABEL: sil @_T019versioned_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
+@_versioned func referencedFromTransparent() {}
+
+// CHECK-LABEL: sil [serialized] @_T019versioned_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
+@_inlineable public func referencesVersionedFunc() -> () -> () {
+  return referencedFromTransparent
+}
+
 @_versioned class Horse {
   var mouth: AnyObject?
 }
diff --git a/test/SILGen/witnesses_class.swift b/test/SILGen/witnesses_class.swift
index 9c5d97a..c2b2dfc 100644
--- a/test/SILGen/witnesses_class.swift
+++ b/test/SILGen/witnesses_class.swift
@@ -26,10 +26,10 @@
 
 // CHECK-LABEL: sil hidden @_T015witnesses_class3genyxAA7FooableRzlF
 // CHECK:         bb0([[SELF:%.*]] : @owned $T)
-// CHECK:         [[METHOD:%.*]] = witness_method $T
 // CHECK-NOT:     copy_value [[SELF]]
 // CHECK:         [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
 // CHECK-NOT:     copy_value [[SELF]]
+// CHECK:         [[METHOD:%.*]] = witness_method $T
 // CHECK:         apply [[METHOD]]<T>([[BORROWED_SELF]])
 // CHECK:         end_borrow [[BORROWED_SELF]] from [[SELF]]
 // CHECK:         destroy_value [[SELF]]
diff --git a/test/SILGen/writeback.swift b/test/SILGen/writeback.swift
index 1232bc6..de739d8 100644
--- a/test/SILGen/writeback.swift
+++ b/test/SILGen/writeback.swift
@@ -43,11 +43,11 @@
 
 // Writeback to value type 'self' argument
 x.foo()
-// CHECK: [[FOO:%.*]] = function_ref @_T09writeback3FooV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout Foo) -> ()
 // CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
 // CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
 // CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
 // CHECK: store [[X]] to [trivial] [[X_TEMP]]
+// CHECK: [[FOO:%.*]] = function_ref @_T09writeback3FooV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout Foo) -> ()
 // CHECK: apply [[FOO]]([[X_TEMP]]) : $@convention(method) (@inout Foo) -> ()
 // CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
 // CHECK: [[SET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
@@ -56,11 +56,11 @@
 
 // Writeback to inout argument
 bar(x: &x)
-// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
 // CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
 // CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
 // CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
 // CHECK: store [[X]] to [trivial] [[X_TEMP]] : $*Foo
+// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
 // CHECK: apply [[BAR]]([[X_TEMP]]) : $@convention(thin) (@inout Foo) -> ()
 // CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
 // CHECK: [[SET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
@@ -81,12 +81,12 @@
 
 // Ensure that subscripts are only evaluated once.
 bar(x: &x[zung()])
-// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
 // CHECK: [[ZUNG:%.*]] = function_ref @_T09writeback4zungSiyF : $@convention(thin) () -> Int
 // CHECK: [[INDEX:%.*]] = apply [[ZUNG]]() : $@convention(thin) () -> Int
 // CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
 // CHECK: [[GET_SUBSCRIPT:%.*]] = function_ref @_T09writeback3FooV{{[_0-9a-zA-Z]*}}ig : $@convention(method) (Int, Foo) -> Foo
 // CHECK: apply [[GET_SUBSCRIPT]]([[INDEX]], {{%.*}}) : $@convention(method) (Int, Foo) -> Foo
+// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
 // CHECK: apply [[BAR]]({{%.*}}) : $@convention(thin) (@inout Foo) -> ()
 // CHECK: [[SET_SUBSCRIPT:%.*]] = function_ref @_T09writeback3FooV{{[_0-9a-zA-Z]*}}is : $@convention(method) (Foo, Int, @inout Foo) -> ()
 // CHECK: apply [[SET_SUBSCRIPT]]({{%.*}}, [[INDEX]], {{%.*}}) : $@convention(method) (Foo, Int, @inout Foo) -> ()
@@ -105,10 +105,10 @@
 func funge(x x: inout Fungible) {}
 
 funge(x: &addressOnly)
-// CHECK: [[FUNGE:%.*]] = function_ref @_T09writeback5fungeyAA8Fungible_pz1x_tF : $@convention(thin) (@inout Fungible) -> ()
 // CHECK: [[TEMP:%.*]] = alloc_stack $Fungible
 // CHECK: [[GET:%.*]] = function_ref @_T09writeback11addressOnlyAA8Fungible_pvg : $@convention(thin) () -> @out Fungible
 // CHECK: apply [[GET]]([[TEMP]]) : $@convention(thin) () -> @out Fungible
+// CHECK: [[FUNGE:%.*]] = function_ref @_T09writeback5fungeyAA8Fungible_pz1x_tF : $@convention(thin) (@inout Fungible) -> ()
 // CHECK: apply [[FUNGE]]([[TEMP]]) : $@convention(thin) (@inout Fungible) -> ()
 // CHECK: [[SET:%.*]] = function_ref @_T09writeback11addressOnlyAA8Fungible_pvs : $@convention(thin) (@in Fungible) -> ()
 // CHECK: apply [[SET]]([[TEMP]]) : $@convention(thin) (@in Fungible) -> ()
@@ -130,8 +130,8 @@
 }
 
 // CHECK-LABEL: sil hidden @_T09writeback12test_generic{{[_0-9a-zA-Z]*}}F 
-// CHECK:         witness_method $Runce.Frob, #Frobable.anse!setter.1
 // CHECK:         witness_method $Runce, #Runcible.frob!materializeForSet.1
+// CHECK:         witness_method $Runce.Frob, #Frobable.anse!setter.1
 func test_generic<Runce: Runcible>(runce runce: inout Runce, anse: Runce.Frob.Anse) {
   runce.frob.anse = anse
 }
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index dbf440e..ed69a81 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -180,3 +180,39 @@
   %closure = partial_apply %f(%var) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
   unreachable
 }
+
+// Borrowed closure can be statically checked.
+//
+// CHECK-LABEL: sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+// CHECK: begin_access [read] [static]
+// CHECK-LABEL: } // end sil function 'borrowedClosure'
+sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+bb0(%0 : $*Builtin.Int64):
+  %access = begin_access [read] [unknown] %0 : $*Builtin.Int64
+  %val = load [trivial] %access : $*Builtin.Int64
+  end_access %access : $*Builtin.Int64
+  %empty = tuple ()
+  return %empty : $()
+}
+
+// Borrow an escaping closure. The closure body will be dynamically checked.
+sil @borrowClosure : $@convention(thin) () -> () {
+  %box = alloc_box ${ var Builtin.Int64 }, var, name "x"
+  %addr = project_box %box : ${ var Builtin.Int64 }, 0
+  // box escapes.
+  %copy = copy_value %box : ${ var Builtin.Int64 }
+
+  %f = function_ref @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+  %closure = partial_apply %f(%addr) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+
+  // closure is borrowed.
+  %borrow = begin_borrow %closure : $@callee_owned () -> ()
+  %closure_copy = copy_value %borrow : $@callee_owned () -> ()
+  end_borrow %borrow from %closure : $@callee_owned () -> (), $@callee_owned () -> ()
+
+  destroy_value %closure_copy : $@callee_owned () -> ()
+  destroy_value %copy : ${ var Builtin.Int64 }
+  destroy_value %box : ${ var Builtin.Int64 }
+  %empty = tuple ()
+  return %empty : $()
+}
diff --git a/test/SILOptimizer/access_marker_mandatory.swift b/test/SILOptimizer/access_marker_mandatory.swift
index ded9e41..feadd10 100644
--- a/test/SILOptimizer/access_marker_mandatory.swift
+++ b/test/SILOptimizer/access_marker_mandatory.swift
@@ -49,9 +49,9 @@
 // CHECK: [[ADDRI:%.*]] = struct_element_addr [[WRITE]] : $*S, #S.i
 // CHECK: store %{{.*}} to [[ADDRI]] : $*Int
 // CHECK: end_access [[WRITE]]
-// CHECK: [[FTAKE:%.*]] = function_ref @_T023access_marker_mandatory5takeSyAA1SVF : $@convention(thin) (@owned S) -> ()
 // CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*S
 // CHECK: end_access [[READ]]
+// CHECK: [[FTAKE:%.*]] = function_ref @_T023access_marker_mandatory5takeSyAA1SVF : $@convention(thin) (@owned S) -> ()
 // CHECK: apply [[FTAKE]](%{{.*}}) : $@convention(thin) (@owned S) -> ()
 // CHECK-LABEL: } // end sil function '_T023access_marker_mandatory14modifyAndReadSyyXl1o_tF'
 public func modifyAndReadS(o: AnyObject) {
diff --git a/test/SILOptimizer/anyhashable_to_protocol.swift b/test/SILOptimizer/anyhashable_to_protocol.swift
new file mode 100644
index 0000000..e4153f5
--- /dev/null
+++ b/test/SILOptimizer/anyhashable_to_protocol.swift
@@ -0,0 +1,18 @@
+// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+protocol FooProtocol : class {
+}
+
+class FooProtocolImplementation : NSObject, FooProtocol {
+}
+
+// CHECK-LABEL: sil @{{.*}}testit
+// CHECK: checked_cast_addr_br {{.*}} AnyHashable {{.*}} to FooProtocol 
+public func testit(_ x: AnyHashable) -> Bool {
+  return (x as? FooProtocol) != nil
+}
+
diff --git a/test/SILOptimizer/character_literals.swift b/test/SILOptimizer/character_literals.swift
index 3254167..109c99b 100644
--- a/test/SILOptimizer/character_literals.swift
+++ b/test/SILOptimizer/character_literals.swift
@@ -1,9 +1,12 @@
-// RUN: %target-swift-frontend -parse-as-library -O -emit-ir  %s | %FileCheck %s
+// RUN: %target-swift-frontend -parse-as-library -O -target-cpu core2 -emit-ir  %s | %FileCheck %s
 // REQUIRES: swift_stdlib_no_asserts,optimized_stdlib,CPU=x86_64
 
 // This is an end-to-end test to ensure that the optimizer generates
 // a simple literal for character literals.
 
+// Please note: this test targets "core2" to ensure consistent output
+// on all x86 host processors.
+
 // CHECK-LABEL: define {{.*}}charArray
 // CHECK:  store <2 x i64> <i64 97, i64 98>
 // CHECK:  store <2 x i64> <i64 99, i64 100>
diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift
index 46d7a51..1d3cc4b 100644
--- a/test/SILOptimizer/definite_init_failable_initializers.swift
+++ b/test/SILOptimizer/definite_init_failable_initializers.swift
@@ -60,7 +60,7 @@
 // CHECK-NEXT:    br bb1
 // CHECK:       bb1:
 // CHECK-NEXT:    [[X_ADDR:%.*]] = struct_element_addr [[SELF_BOX]]
-// CHECK-NEXT:    strong_release [[CANARY]]
+// CHECK-NEXT:    destroy_addr [[X_ADDR]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    [[SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
 // CHECK-NEXT:    br bb2
@@ -86,8 +86,7 @@
 // CHECK-NEXT:    end_access [[WRITE]] : $*FailableStruct
 // CHECK-NEXT:    br bb1
 // CHECK:       bb1:
-// CHECK-NEXT:    [[SELF:%.*]] = struct $FailableStruct ([[CANARY1]] : $Canary, [[CANARY2]] : $Canary)
-// CHECK-NEXT:    release_value [[SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
 // CHECK-NEXT:    br bb2
@@ -108,7 +107,7 @@
 // CHECK-NEXT:    end_access [[WRITE]] : $*FailableStruct
 // CHECK-NEXT:    br bb1
 // CHECK:       bb1:
-// CHECK-NEXT:    release_value [[CANARY]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    [[SELF_VALUE:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
 // CHECK-NEXT:    br bb2
@@ -127,7 +126,7 @@
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
 // CHECK-NEXT:    br bb1
 // CHECK:       bb1:
-// CHECK-NEXT:    release_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
 // CHECK-NEXT:    br bb2
@@ -153,7 +152,9 @@
 // CHECK:       [[SUCC_BB]]:
 // CHECK-NEXT:    [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
 // CHECK-NEXT:    store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT:    retain_value [[SELF_VALUE]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableStruct>)
 //
@@ -225,9 +226,9 @@
 // CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers22FailableAddrOnlyStructV{{[_0-9a-zA-Z]*}}failAfterPartialInitialization{{.*}}tcfC
 // CHECK:       bb0(%0 : $*Optional<FailableAddrOnlyStruct<T>>, %1 : $@thin FailableAddrOnlyStruct<T>.Type):
 // CHECK:         [[SELF_BOX:%.*]] = alloc_stack $FailableAddrOnlyStruct<T>
-// CHECK:         [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
-// CHECK-NEXT:    [[X_BOX:%.*]] = alloc_stack $T
+// CHECK:         [[X_BOX:%.*]] = alloc_stack $T
 // CHECK-NEXT:    [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK:         [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
 // CHECK-NEXT:    apply [[T_INIT_FN]]<T>([[X_BOX]], [[T_TYPE]])
 // CHECK-NEXT:    [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
 // CHECK-NEXT:    [[X_ADDR:%.*]] = struct_element_addr [[WRITE]]
@@ -251,18 +252,18 @@
 // CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers22FailableAddrOnlyStructV{{[_0-9a-zA-Z]*}}failAfterFullInitialization{{.*}}tcfC
 // CHECK:       bb0(%0 : $*Optional<FailableAddrOnlyStruct<T>>, %1 : $@thin FailableAddrOnlyStruct<T>.Type):
 // CHECK:         [[SELF_BOX:%.*]] = alloc_stack $FailableAddrOnlyStruct<T>
-// CHECK:         [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
-// CHECK-NEXT:    [[X_BOX:%.*]] = alloc_stack $T
+// CHECK:         [[X_BOX:%.*]] = alloc_stack $T
 // CHECK-NEXT:    [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK:         [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
 // CHECK-NEXT:    apply [[T_INIT_FN]]<T>([[X_BOX]], [[T_TYPE]])
 // CHECK-NEXT:    [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
 // CHECK-NEXT:    [[X_ADDR:%.*]] = struct_element_addr [[WRITE]]
 // CHECK-NEXT:    copy_addr [take] [[X_BOX]] to [initialization] [[X_ADDR]]
 // CHECK-NEXT:    end_access [[WRITE]] : $*FailableAddrOnlyStruct<T>
 // CHECK-NEXT:    dealloc_stack [[X_BOX]]
-// CHECK-NEXT:    [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
 // CHECK-NEXT:    [[Y_BOX:%.*]] = alloc_stack $T
 // CHECK-NEXT:    [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK-NEXT:    [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
 // CHECK-NEXT:    apply [[T_INIT_FN]]<T>([[Y_BOX]], [[T_TYPE]])
 // CHECK-NEXT:    [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
 // CHECK-NEXT:    [[Y_ADDR:%.*]] = struct_element_addr [[WRITE]]
@@ -346,6 +347,8 @@
 // CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt6noFail_tcfC
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = apply [[INIT_FN]](%1)
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -366,6 +369,8 @@
 // CHECK-NEXT:    try_apply [[INIT_FN]](%1)
 // CHECK:       bb2([[NEW_SELF:%.*]] : $ThrowStruct):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb3([[ERROR:%.*]] : $Error):
@@ -383,10 +388,10 @@
 // CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi29failBeforeOrDuringDelegation2_tKcfC
 // CHECK:       bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
 // CHECK:         [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
-// CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACSi20failBeforeDelegation_tKcfC
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb1([[RESULT:%.*]] : $Int):
+// CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACSi20failBeforeDelegation_tKcfC
 // CHECK-NEXT:    try_apply [[INIT_FN]]([[RESULT]], %1)
 // CHECK:       bb2([[NEW_SELF:%.*]] : $ThrowStruct):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
@@ -410,6 +415,8 @@
 // CHECK-NEXT:    try_apply [[INIT_FN]](%1)
 // CHECK:       bb1([[NEW_SELF:%.*]] : $ThrowStruct):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -428,10 +435,12 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
-// CHECK:         release_value [[NEW_SELF]]
+// CHECK:         destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    throw [[ERROR]]
   init(failAfterDelegation: Int) throws {
@@ -454,6 +463,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
@@ -493,6 +504,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
@@ -537,7 +550,9 @@
 // CHECK:       [[SUCC_BB]]:
 // CHECK-NEXT:    [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
 // CHECK-NEXT:    store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT:    retain_value [[SELF_VALUE]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<ThrowStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<ThrowStruct>)
 //
@@ -584,13 +599,15 @@
 // CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi25failDuringSelfReplacement_tKcfC
 // CHECK:       bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
 // CHECK-NEXT:    [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
+// CHECK:         [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
 // CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt4fail_tKcfC
-// CHECK-NEXT:    [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
 // CHECK-NEXT:    try_apply [[INIT_FN]]([[SELF_TYPE]])
 // CHECK:       bb1([[NEW_SELF:%.*]] : $ThrowStruct):
 // CHECK-NEXT:    [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*ThrowStruct
 // CHECK-NEXT:    store [[NEW_SELF]] to [[WRITE]]
 // CHECK-NEXT:    end_access [[WRITE]] : $*ThrowStruct
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -603,8 +620,8 @@
 // CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi24failAfterSelfReplacement_tKcfC
 // CHECK:       bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
 // CHECK-NEXT:    [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
+// CHECK:         [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
 // CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt6noFail_tcfC
-// CHECK-NEXT:    [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = apply [[INIT_FN]]([[SELF_TYPE]])
 // CHECK-NEXT:    [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*ThrowStruct
 // CHECK-NEXT:    store [[NEW_SELF]] to [[WRITE]]
@@ -612,10 +629,12 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    retain_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT:    release_value [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    throw [[ERROR]]
   init(failAfterSelfReplacement: Int) throws {
@@ -782,7 +801,7 @@
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
 // CHECK-NEXT:    br bb1
 // CHECK:       bb1:
-// CHECK-NEXT:    strong_release [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    [[RESULT:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
 // CHECK-NEXT:    br bb2
@@ -809,7 +828,9 @@
 // CHECK:       [[SUCC_BB]]:
 // CHECK-NEXT:    [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
 // CHECK-NEXT:    store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[SELF_VALUE]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<FailableBaseClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableBaseClass>)
 //
@@ -891,7 +912,9 @@
 // CHECK-NEXT:    [[BASE_SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
 // CHECK-NEXT:    [[SELF_VALUE:%.*]] = unchecked_ref_cast [[BASE_SELF_VALUE]]
 // CHECK-NEXT:    store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[SELF_VALUE]]
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = enum $Optional<FailableDerivedClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableDerivedClass>)
 //
@@ -952,6 +975,8 @@
 // CHECK:       bb1([[NEW_SELF:%.*]] : $ThrowBaseClass):
 // CHECK-NEXT:    [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
 // CHECK-NEXT:    store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -977,6 +1002,8 @@
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = apply [[INIT_FN]]([[BASE_SELF]])
 // CHECK-NEXT:    [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
 // CHECK-NEXT:    store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]] : $ThrowDerivedClass
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -1007,6 +1034,8 @@
 // CHECK:       bb2([[NEW_SELF:%.*]] : $ThrowBaseClass):
 // CHECK-NEXT:    [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
 // CHECK-NEXT:    store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
@@ -1044,10 +1073,12 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT:    strong_release [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    throw [[ERROR]]
   init(failAfterFullInitialization: Int) throws {
@@ -1073,6 +1104,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
@@ -1122,6 +1155,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%1)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
@@ -1184,6 +1219,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%2)
 // CHECK:       bb3([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[DERIVED_SELF]]
@@ -1239,6 +1276,8 @@
 // CHECK:         [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers17ThrowDerivedClassCACyt6noFail_tcfc
 // CHECK-NEXT:    [[NEW_SELF:%.*]] = apply [[INIT_FN]](%1)
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -1259,6 +1298,8 @@
 // CHECK-NEXT:    try_apply [[INIT_FN]](%1)
 // CHECK:       bb1([[NEW_SELF:%.*]] : $ThrowDerivedClass):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
@@ -1284,6 +1325,8 @@
 // CHECK-NEXT:    try_apply [[INIT_FN]](%1)
 // CHECK:       bb2([[NEW_SELF:%.*]] : $ThrowDerivedClass):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
@@ -1325,6 +1368,8 @@
 // CHECK-NEXT:    try_apply [[INIT_FN]]([[ARG]], %1)
 // CHECK:       bb2([[NEW_SELF:%.*]] : $ThrowDerivedClass):
 // CHECK-NEXT:    store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
@@ -1361,10 +1406,12 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
 // CHECK:       bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT:    strong_release [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    throw [[ERROR]]
   convenience init(failAfterDelegation: Int) throws {
@@ -1390,6 +1437,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
@@ -1437,6 +1486,8 @@
 // CHECK:         [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
 // CHECK-NEXT:    try_apply [[UNWRAP_FN]](%0)
 // CHECK:       bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT:    strong_retain [[NEW_SELF]]
+// CHECK-NEXT:    destroy_addr [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[SELF_BOX]]
 // CHECK-NEXT:    dealloc_stack [[BITMAP_BOX]]
 // CHECK-NEXT:    return [[NEW_SELF]]
diff --git a/test/SILOptimizer/definite_init_failable_initializers_objc.swift b/test/SILOptimizer/definite_init_failable_initializers_objc.swift
index a9126d0..9a5810c 100644
--- a/test/SILOptimizer/definite_init_failable_initializers_objc.swift
+++ b/test/SILOptimizer/definite_init_failable_initializers_objc.swift
@@ -50,7 +50,10 @@
     // CHECK-NEXT: [[NEW_SUPER_SELF:%.*]] = apply [[SUPER_FN]]([[SUPER]]) : $@convention(objc_method) (@owned FakeNSObject) -> @owned FakeNSObject
     // CHECK-NEXT: [[NEW_SELF:%.*]] = unchecked_ref_cast [[NEW_SUPER_SELF]] : $FakeNSObject to $Cat
     // CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]] : $*Cat
+    // TODO: Once we re-enable arbitrary take promotion, this retain and the associated destroy_addr will go away.
+    // CHECK-NEXT: strong_retain [[NEW_SELF]]
     // CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<Cat>, #Optional.some!enumelt.1, [[NEW_SELF]] : $Cat
+    // CHECK-NEXT: destroy_addr [[SELF_BOX]]
     // CHECK-NEXT: dealloc_stack [[SELF_BOX]] : $*Cat
     // CHECK-NEXT: br bb4([[RESULT]] : $Optional<Cat>)
 
diff --git a/test/SILOptimizer/definite_init_objc_factory_init.swift b/test/SILOptimizer/definite_init_objc_factory_init.swift
index 3ddeef5..1002361 100644
--- a/test/SILOptimizer/definite_init_objc_factory_init.swift
+++ b/test/SILOptimizer/definite_init_objc_factory_init.swift
@@ -26,8 +26,8 @@
     // CHECK: [[SELF_ADDR:%[0-9]+]] = alloc_stack $Hive
     // CHECK: store [[OLD_SELF:%[0-9]+]] to [[SELF_ADDR]]
     // CHECK: [[META:%[0-9]+]] = value_metatype $@thick Hive.Type, [[OLD_SELF]] : $Hive
-    // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[META]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
     // CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[META]] : $@thick Hive.Type to $@objc_metatype Hive.Type
+    // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[OBJC_META]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
     // CHECK: apply [[FACTORY]]([[QUEEN:%[0-9]+]], [[OBJC_META]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
     // CHECK: store [[NEW_SELF:%[0-9]+]] to [[SELF_ADDR]]
     // CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[OLD_SELF]] : $Hive
@@ -58,8 +58,8 @@
   convenience init(delegatesToInherited: ()) {
     // CHECK: [[UPCAST:%.*]] = upcast %0 : $SubHive to $Hive
     // CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST]] : $Hive
-    // CHECK: [[METHOD:%.*]] = objc_method [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
     // CHECK: [[OBJC:%.*]] = thick_to_objc_metatype [[METATYPE]] : $@thick Hive.Type to $@objc_metatype Hive.Type
+    // CHECK: [[METHOD:%.*]] = objc_method [[OBJC]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
     // CHECK: apply [[METHOD]]({{.*}}, [[OBJC]])
 
     // CHECK: [[METATYPE:%.*]] = value_metatype $@thick SubHive.Type, %0 : $SubHive
diff --git a/test/SILOptimizer/definite_init_protocol_init.swift b/test/SILOptimizer/definite_init_protocol_init.swift
index 79d69fe..ff72ad8 100644
--- a/test/SILOptimizer/definite_init_protocol_init.swift
+++ b/test/SILOptimizer/definite_init_protocol_init.swift
@@ -31,15 +31,18 @@
   // CHECK-NEXT:  debug_value
   // CHECK-NEXT:  store [[OLD_SELF]] to [[SELF_BOX]]
   // CHECK-NEXT:  [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self TrivialClass.Type, %1
+  // CHECK-NEXT:  [[RESULT:%.*]] = alloc_stack $TrivialClass
   // CHECK-NEXT:  // function_ref
   // CHECK-NEXT:  [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-  // CHECK-NEXT:  [[RESULT:%.*]] = alloc_stack $TrivialClass
   // CHECK-NEXT:  apply [[FN]]<@dynamic_self TrivialClass>([[RESULT]], %0, [[METATYPE]])
   // CHECK-NEXT:  [[NEW_SELF:%.*]] = load [[RESULT]]
   // CHECK-NEXT:  store [[NEW_SELF]] to [[SELF_BOX]]
   // CHECK-NEXT:  [[METATYPE:%.*]] = value_metatype $@thick TrivialClass.Type, %1
   // CHECK-NEXT:  dealloc_partial_ref %1 : $TrivialClass, [[METATYPE]] : $@thick TrivialClass.Type
   // CHECK-NEXT:  dealloc_stack [[RESULT]]
+  // TODO: Once we restore arbitrary takes, the strong_retain/destroy_addr pair below will go away.
+  // CHECK-NEXT:  strong_retain [[NEW_SELF]]
+  // CHECK-NEXT:  destroy_addr [[SELF_BOX]]
   // CHECK-NEXT:  dealloc_stack [[SELF_BOX]]
   // CHECK-NEXT:  return [[NEW_SELF]]
   convenience init(upper: Int) {
@@ -63,9 +66,9 @@
 // CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B013TrivialStructVACSi5upper_tcfC
 // CHECK:     bb0(%0 : $Int, %1 : $@thin TrivialStruct.Type):
 // CHECK-NEXT: [[SELF:%.*]] = alloc_stack $TrivialStruct
-// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $TrivialStruct
+// CHECK:      [[SELF_BOX:%.*]] = alloc_stack $TrivialStruct
 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialStruct.Type
+// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
 // CHECK-NEXT: apply [[FN]]<TrivialStruct>([[SELF_BOX]], %0, [[METATYPE]])
 // CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
 // CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
@@ -93,9 +96,9 @@
 // CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B017AddressOnlyStructVACSi5upper_tcfC
 // CHECK:     bb0(%0 : $*AddressOnlyStruct, %1 : $Int, %2 : $@thin AddressOnlyStruct.Type):
 // CHECK-NEXT: [[SELF:%.*]] = alloc_stack $AddressOnlyStruct
-// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $AddressOnlyStruct
+// CHECK:      [[SELF_BOX:%.*]] = alloc_stack $AddressOnlyStruct
 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick AddressOnlyStruct.Type
+// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
 // CHECK-NEXT: apply [[FN]]<AddressOnlyStruct>([[SELF_BOX]], %1, [[METATYPE]])
 // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [initialization] [[SELF]]
 // CHECK-NEXT: dealloc_stack [[SELF_BOX]]
@@ -126,9 +129,9 @@
 // CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B011TrivialEnumOACSi5upper_tcfC
 // CHECK:     bb0(%0 : $Int, %1 : $@thin TrivialEnum.Type):
 // CHECK-NEXT: [[SELF:%.*]] = alloc_stack $TrivialEnum
-// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $TrivialEnum
+// CHECK:      [[SELF_BOX:%.*]] = alloc_stack $TrivialEnum
 // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialEnum.Type
+// CHECK:      [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
 // CHECK-NEXT: apply [[FN]]<TrivialEnum>([[SELF_BOX]], %0, [[METATYPE]])
 // CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
 // CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
diff --git a/test/SILOptimizer/devirt_conditional_conformance.swift b/test/SILOptimizer/devirt_conditional_conformance.swift
new file mode 100644
index 0000000..a992775
--- /dev/null
+++ b/test/SILOptimizer/devirt_conditional_conformance.swift
@@ -0,0 +1,56 @@
+// RUN: %target-swift-frontend -O -Xllvm -sil-inline-generics=false -Xllvm -sil-disable-pass=GlobalOpt %s -emit-sil -sil-verify-all | %FileCheck %s
+
+
+public protocol Foo {
+  func foo_method()
+}
+public protocol Bar {
+  func bar_method()
+}
+
+@inline(never)
+func bar_marker() {}
+
+public struct Inner: Bar {
+  public func bar_method() {
+    bar_marker()
+  }
+}
+
+public struct Outer<T> {
+  var x: T
+}
+
+@inline(never)
+func foo_marker() {}
+extension Outer: Foo where T: Bar {
+  public func foo_method() {
+    foo_marker()
+    x.bar_method()
+  }
+}
+
+func callFoo<T: Foo>(_ x: T) {
+  x.foo_method()
+}
+
+func genericLayer<T: Bar>(_ x: T) {
+  callFoo(Outer(x: x))
+}
+
+// See that we devirtualize/inline enough to get down to the @inline(never)
+// function calls.
+
+// CHECK-LABEL: sil @_T030devirt_conditional_conformance12throughLayeryyF : $@convention(thin) () -> ()
+// CHECK: function_ref @_T030devirt_conditional_conformance10foo_markeryyF
+// CHECK: function_ref @_T030devirt_conditional_conformance10bar_markeryyF
+public func throughLayer() {
+  genericLayer(Inner())
+}
+
+// CHECK-LABEL: sil @_T030devirt_conditional_conformance6directyyF : $@convention(thin) () -> ()
+// CHECK: function_ref @_T030devirt_conditional_conformance10foo_markeryyF
+// CHECK: function_ref @_T030devirt_conditional_conformance10bar_markeryyF
+public func direct() {
+  callFoo(Outer(x: Inner()))
+}
diff --git a/test/SILOptimizer/devirt_materializeForSet.swift b/test/SILOptimizer/devirt_materializeForSet.swift
index 1e87bec..de9f12f 100644
--- a/test/SILOptimizer/devirt_materializeForSet.swift
+++ b/test/SILOptimizer/devirt_materializeForSet.swift
@@ -2,12 +2,10 @@
 
 // Check that compiler does not crash on the devirtualization of materializeForSet methods
 // and produces a correct code.
+//
+// Note: now we no longer speculatively devirtualize inside thunks, so this test does nothing.
 
 // CHECK-LABEL: sil shared [transparent] [thunk] @_T024devirt_materializeForSet7BaseFooCAA0F0A2aDP3barSSvmTW
-// CHECK: checked_cast_br [exact] %{{.*}} : $BaseFoo to $ChildFoo
-// CHECK: thin_function_to_pointer %{{.*}} : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer
-// CHECK: enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, %{{.*}} : $Builtin.RawPointer
-// CHECK: tuple (%{{.*}} : $Builtin.RawPointer, %{{.*}} : $Optional<Builtin.RawPointer>)
 
 public protocol Foo {
     var bar: String { get set }
diff --git a/test/SILOptimizer/devirt_static_covariant_return.swift b/test/SILOptimizer/devirt_static_covariant_return.swift
new file mode 100644
index 0000000..fa52598
--- /dev/null
+++ b/test/SILOptimizer/devirt_static_covariant_return.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -O -whole-module-optimization %s -emit-sil -sil-verify-all | %FileCheck %s
+
+// CHECK-NOT: class_method
+
+// Static method returning Self in generic class
+public class Factory<T> {
+  public required init() {}
+
+  @inline(never) class func bar() -> Self {
+    return self.init()
+  }
+
+  @inline(never) class func foo() -> Self {
+    return bar()
+  }
+}
+
+public func foo(m: Factory<Int>.Type) {
+  m.foo()
+}
diff --git a/test/SILOptimizer/generic_inline_self.swift b/test/SILOptimizer/generic_inline_self.swift
index 7351c27..367e809 100644
--- a/test/SILOptimizer/generic_inline_self.swift
+++ b/test/SILOptimizer/generic_inline_self.swift
@@ -27,8 +27,8 @@
 
 // CHECK-LABEL: sil hidden @_T019generic_inline_self1CC18returnsNewInstanceACXDyF : $@convention(method) (@guaranteed C) -> @owned C
 // CHECK:       bb0(%0 : $C):
+// CHECK:         [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self C.Type, %0 : $C
 // CHECK:         [[FN:%.*]] = function_ref @_T019generic_inline_self12makeInstancexxmAA1CCRbzlF : $@convention(thin) <τ_0_0 where τ_0_0 : C> (@thick τ_0_0.Type) -> @owned τ_0_0
-// CHECK-NEXT:    [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self C.Type, %0 : $C
 // CHECK-NEXT:    [[RESULT:%.*]] = apply [[FN]]<@dynamic_self C>([[METATYPE]]) : $@convention(thin) <τ_0_0 where τ_0_0 : C> (@thick τ_0_0.Type) -> @owned τ_0_0
 // CHECK-NEXT:    return [[RESULT]] : $C
   func returnsNewInstance() -> Self {
diff --git a/test/SILOptimizer/inline_recursive.swift b/test/SILOptimizer/inline_recursive.swift
index 0440fbf..2f0dfd8 100644
--- a/test/SILOptimizer/inline_recursive.swift
+++ b/test/SILOptimizer/inline_recursive.swift
@@ -9,9 +9,9 @@
 
 // CHECK-LABEL: sil {{.*}}callit
 // CHECK: bb0:
-// CHECK: [[REF:%.*]] = function_ref @_T016inline_recursive7recFunc33_38E63D320CFF538A1F98BBC31453B1EBLLs5Int32VAEF
 // CHECK: [[INTLIT:%.*]] = integer_literal $Builtin.Int32, 3
 // CHECK: [[STRUCT:%.*]] = struct $Int32 ([[INTLIT]] : $Builtin.Int32)
+// CHECK: [[REF:%.*]] = function_ref @_T016inline_recursive7recFunc33_38E63D320CFF538A1F98BBC31453B1EBLLs5Int32VAEF
 // CHECK: [[APPLY:%.*]] = apply [[REF]]([[STRUCT]])
 // CHECK: return [[APPLY]]
 
diff --git a/test/SILOptimizer/inline_self.swift b/test/SILOptimizer/inline_self.swift
index 79e657b..ec93abb 100644
--- a/test/SILOptimizer/inline_self.swift
+++ b/test/SILOptimizer/inline_self.swift
@@ -76,9 +76,9 @@
 // CHECK: [[F:%[0-9]+]] = function_ref @_T011inline_self1CC7factory{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (Int, @thick C.Type) -> @owned C
 // CHECK: apply [[F]](%{{.+}}, %{{.+}}) : $@convention(method) (Int, @thick C.Type) -> @owned C
 
+// CHECK: [[Z:%.*]] = alloc_ref $Z
 // CHECK: function_ref inline_self.Z.capturesSelf() -> Self
 // CHECK: [[F:%[0-9]+]] = function_ref @_T011inline_self1ZC12capturesSelfACXDyF : $@convention(method) (@guaranteed Z) -> @owned Z
-// CHECK: [[Z:%.*]] = alloc_ref $Z
 // CHECK: apply [[F]]([[Z]]) : $@convention(method) (@guaranteed Z) -> @owned
 // CHECK: return
 
diff --git a/test/SILOptimizer/inliner_coldblocks.sil b/test/SILOptimizer/inliner_coldblocks.sil
index 18ec8a5..58d5c68 100644
--- a/test/SILOptimizer/inliner_coldblocks.sil
+++ b/test/SILOptimizer/inliner_coldblocks.sil
@@ -193,7 +193,7 @@
   %c30 = builtin "assert_configuration"() : $Builtin.Int32
 
   %f = function_ref @update_global: $@convention(thin) () -> ()
-  // REMARKS_PASSED: inliner_coldblocks.sil:223:3: remark: update_global inlined into regular_large_callee (cost = {{.*}}, benefit = {{.*}})
+  // REMARKS_PASSED: inliner_coldblocks.sil:223:3: remark: "update_global" inlined into "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
   // YAML:      --- !Passed
   // YAML-NEXT: Pass:            sil-inliner
   // YAML-NEXT: Name:            Inlined
@@ -203,13 +203,13 @@
   // YAML-NEXT:   Column:          3
   // YAML-NEXT: Function:        regular_large_callee
   // YAML-NEXT: Args:
-  // YAML-NEXT:   - Callee:          update_global
+  // YAML-NEXT:   - Callee:          '"update_global"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}inliner_coldblocks.sil
   // YAML-NEXT:       Line:            20
   // YAML-NEXT:       Column:          6
   // YAML-NEXT:   - String:          ' inlined into '
-  // YAML-NEXT:   - Caller:          regular_large_callee
+  // YAML-NEXT:   - Caller:          '"regular_large_callee"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}inliner_coldblocks.sil
   // YAML-NEXT:       Line:            162
@@ -233,17 +233,23 @@
 sil @dont_inline_regular_large_callee : $@convention(thin) () -> () {
 bb0:
   %f = function_ref @regular_large_callee : $@convention(thin) () -> ()
-  // REMARKS_MISSED: inliner_coldblocks.sil:252:8: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+  // REMARKS_MISSED: inliner_coldblocks.sil:258:8: remark: Not profitable to inline function "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
   // YAML:      --- !Missed
   // YAML-NEXT: Pass:            sil-inliner
   // YAML-NEXT: Name:            NoInlinedCost
   // YAML-NEXT: DebugLoc:
   // YAML-NEXT:   File:            {{.*}}inliner_coldblocks.sil
-  // YAML-NEXT:   Line:            252
+  // YAML-NEXT:   Line:            258
   // YAML-NEXT:   Column:          8
   // YAML-NEXT: Function:        dont_inline_regular_large_callee
   // YAML-NEXT: Args:
-  // YAML-NEXT:   - String:          'Not profitable to inline (cost = '
+  // YAML-NEXT:   - String:          'Not profitable to inline function '
+  // YAML-NEXT:   - Callee:          '"regular_large_callee"'
+  // YAML-NEXT:     DebugLoc:
+  // YAML-NEXT:       File:            {{.*}}inliner_coldblocks.sil
+  // YAML-NEXT:       Line:            162
+  // YAML-NEXT:       Column:          6
+  // YAML-NEXT:   - String:          ' (cost = '
   // YAML-NEXT:   - Cost:            '{{.*}}'
   // YAML-NEXT:   - String:          ', benefit = '
   // YAML-NEXT:   - Benefit:         '{{.*}}'
diff --git a/test/SILOptimizer/linker.swift b/test/SILOptimizer/linker.swift
index 7959a07..8a17b90 100644
--- a/test/SILOptimizer/linker.swift
+++ b/test/SILOptimizer/linker.swift
@@ -13,9 +13,9 @@
 
 // CHECK: sil @unknown
 
+// CHECK: sil @_T0s1AVABycfC
+
 // CHECK: sil [noinline] @_T0s12doSomething3yxlF
 // CHECK-NOT: return
 
-// CHECK: sil @_T0s1AVABycfC
-
 callDoSomething3()
diff --git a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
index 425d4a6..8a4665b 100644
--- a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
+++ b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
@@ -1,5 +1,6 @@
 // RUN: %target-swift-frontend -enable-sil-ownership -sil-verify-all -primary-file %s -module-name=test -emit-sil -o - -verify | %FileCheck %s
 
+struct X { }
 
 // CHECK-LABEL: sil {{.*}} @{{.*}}generic_func
 // CHECK: switch_enum_addr
@@ -11,28 +12,28 @@
 // CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_nil
 // CHECK: switch_enum_addr
 // CHECK: return
-func array_func_rhs_nil(x: [Int]?) -> Bool {
+func array_func_rhs_nil(x: [X]?) -> Bool {
   return x == nil
 }
 
 // CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_nil
 // CHECK: switch_enum_addr
 // CHECK: return
-func array_func_lhs_nil(x: [Int]?) -> Bool {
+func array_func_lhs_nil(x: [X]?) -> Bool {
   return nil == x
 }
 
 // CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_non_nil
 // CHECK: switch_enum_addr
 // CHECK: return
-func array_func_rhs_non_nil(x: [Int]?) -> Bool {
+func array_func_rhs_non_nil(x: [X]?) -> Bool {
   return x != nil
 }
 
 // CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_non_nil
 // CHECK: switch_enum_addr
 // CHECK: return
-func array_func_lhs_non_nil(x: [Int]?) -> Bool {
+func array_func_lhs_non_nil(x: [X]?) -> Bool {
   return nil != x
 }
 
diff --git a/test/SILOptimizer/opt_mode.swift b/test/SILOptimizer/opt_mode.swift
new file mode 100644
index 0000000..d2257d7
--- /dev/null
+++ b/test/SILOptimizer/opt_mode.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-frontend  -primary-file %s -O -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend  -primary-file %s -Osize -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend  -primary-file %s -O -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// RUN: %target-swift-frontend  -primary-file %s -Osize -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
+
+class A {
+  func foo(_ x: Int) -> Int { return x }
+}
+
+class B : A {
+  override func foo(_ x: Int) -> Int { return x + 1 }
+}
+
+
+func donothing(_ x: Int) -> Int { return x }
+
+// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
+// CHECK: checked_cast_br
+// CHECK: checked_cast_br
+// CHECK: }
+// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(speed)
+func test_ospeed(_ a: A) -> Int {
+  return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: return [[A]]
+// CHECK-IR: define hidden {{.*}}test_osize{{.*}} [[SIZE_ATTR:#[0-9]+]]
+@_optimize(size)
+func test_osize(_ a: A) -> Int {
+  return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Onone] @{{.*}}test_onone
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: [[A2:%[0-9]+]] = apply
+// CHECK: return [[A2]]
+// CHECK-IR: define hidden {{.*}}test_onone{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(none)
+func test_onone(_ a: A) -> Int {
+  return donothing(a.foo(27))
+}
+
+
+// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
+// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
diff --git a/test/SILOptimizer/partial_specialization_debug.sil b/test/SILOptimizer/partial_specialization_debug.sil
new file mode 100644
index 0000000..2fd5eb4
--- /dev/null
+++ b/test/SILOptimizer/partial_specialization_debug.sil
@@ -0,0 +1,66 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -generic-specializer -sil-partial-specialization=0 -sil-partial-specialization-with-generic-substitutions -debug-only=generic-specializer %s -o /dev/null 2>&1 | %FileCheck %s
+
+// REQUIRES: asserts
+
+// Test the debug messages from Generic Specialization.  It's based on
+// partial_specialization.sil.
+
+// CHECK: *** ApplyInst in function simple_generic_caller1:
+// CHECK:     Partial specialization is not supported.{{$}}
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+@_silgen_name("use")
+public func use<T>(_ t: T)
+
+@inline(never) public func simple_generic_callee<U, V>(_ u: U, _ v: V)
+
+public func simple_generic_caller1<U>(_ u: U)
+
+// use
+sil @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+
+// simple_generic_callee<A, B>(_:_:)
+sil [noinline] @simple_generic_callee : $@convention(thin) <U, V> (@in U, @in V) -> () {
+bb0(%0 : $*U, %1 : $*V):
+  // function_ref use
+  %4 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+  %5 = alloc_stack $U
+  copy_addr %0 to [initialization] %5 : $*U
+  %7 = apply %4<U>(%5) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+  dealloc_stack %5 : $*U
+  // function_ref use
+  %9 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+  %10 = alloc_stack $V
+  copy_addr %1 to [initialization] %10 : $*V
+  %12 = apply %9<V>(%10) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+  dealloc_stack %10 : $*V
+  destroy_addr %1 : $*V
+  destroy_addr %0 : $*U
+  %16 = tuple ()
+  return %16 : $()
+} // end sil function 'simple_generic_callee'
+
+// simple_generic_caller1<A>(_:)
+sil @simple_generic_caller1 : $@convention(thin) <U> (@in U) -> () {
+bb0(%0 : $*U):
+  // function_ref simple_generic_callee<A, B>(_:_:)
+  %2 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
+  %3 = alloc_stack $U
+  copy_addr %0 to [initialization] %3 : $*U
+  %5 = integer_literal $Builtin.Int32, 1
+  %6 = struct $Int32 (%5 : $Builtin.Int32)
+  %7 = alloc_stack $Int32
+  store %6 to %7 : $*Int32
+  %9 = apply %2<U, Int32>(%3, %7) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
+  dealloc_stack %7 : $*Int32
+  dealloc_stack %3 : $*U
+  destroy_addr %0 : $*U
+  %13 = tuple ()
+  return %13 : $()
+} // end sil function 'simple_generic_caller1'
+
diff --git a/test/SILOptimizer/pointer_conversion.swift b/test/SILOptimizer/pointer_conversion.swift
index c408fb4..4c3eaae 100644
--- a/test/SILOptimizer/pointer_conversion.swift
+++ b/test/SILOptimizer/pointer_conversion.swift
@@ -22,10 +22,10 @@
 public func testArray() {
   let array: [Int] = get()
   takesConstRawPointer(array)
-  // CHECK: [[FN:%.+]] = function_ref @takesConstRawPointer
   // CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
   // CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeRawPointer (
   // CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]] : $Optional<AnyObject>
+  // CHECK: [[FN:%.+]] = function_ref @takesConstRawPointer
   // CHECK-NEXT: apply [[FN]]([[DEP_POINTER]])
   // CHECK-NOT: release
   // CHECK-NOT: {{^bb[0-9]+:}}
@@ -38,11 +38,11 @@
 public func testArrayToOptional() {
   let array: [Int] = get()
   takesOptConstRawPointer(array)
-  // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
   // CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
   // CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeRawPointer (
   // CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]] : $Optional<AnyObject>
   // CHECK-NEXT: [[OPT_POINTER:%.+]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEP_POINTER]]
+  // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
   // CHECK-NEXT: apply [[FN]]([[OPT_POINTER]])
   // CHECK-NOT: release
   // CHECK-NOT: {{^bb[0-9]+:}}
@@ -55,10 +55,10 @@
 public func testMutableArray() {
   var array: [Int] = get()
   takesMutableRawPointer(&array)
-  // CHECK: [[FN:%.+]] = function_ref @takesMutableRawPointer
   // CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
   // CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeMutableRawPointer (
   // CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]] : $Optional<AnyObject>
+  // CHECK: [[FN:%.+]] = function_ref @takesMutableRawPointer
   // CHECK-NEXT: apply [[FN]]([[DEP_POINTER]])
   // CHECK-NOT: release
   // CHECK-NOT: {{^bb[0-9]+:}}
@@ -72,11 +72,11 @@
 public func testMutableArrayToOptional() {
   var array: [Int] = get()
   takesOptMutableRawPointer(&array)
-  // CHECK: [[FN:%.+]] = function_ref @takesOptMutableRawPointer
   // CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
   // CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeMutableRawPointer (
   // CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]] : $Optional<AnyObject>
   // CHECK-NEXT: [[OPT_POINTER:%.+]] = enum $Optional<UnsafeMutableRawPointer>, #Optional.some!enumelt.1, [[DEP_POINTER]]
+  // CHECK: [[FN:%.+]] = function_ref @takesOptMutableRawPointer
   // CHECK-NEXT: apply [[FN]]([[OPT_POINTER]])
   // CHECK-NOT: release
   // CHECK-NOT: {{^bb[0-9]+:}}
@@ -98,8 +98,8 @@
 
   // CHECK: [[CALL_BRANCH]]([[OPT_POINTER:%.+]] : $Optional<UnsafeRawPointer>, [[OWNER:%.+]] : $Optional<AnyObject>):
   // CHECK-NOT: release
-  // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
   // CHECK-NEXT: [[DEP_OPT_POINTER:%.+]] = mark_dependence [[OPT_POINTER]] : $Optional<UnsafeRawPointer> on [[OWNER]] : $Optional<AnyObject>
+  // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
   // CHECK-NEXT: apply [[FN]]([[DEP_OPT_POINTER]])
   // CHECK-NOT: release
   // CHECK-NOT: {{^bb[0-9]+:}}
diff --git a/test/SILOptimizer/predictable_memopt.sil b/test/SILOptimizer/predictable_memopt.sil
index 4e2ccdf..75ffb68 100644
--- a/test/SILOptimizer/predictable_memopt.sil
+++ b/test/SILOptimizer/predictable_memopt.sil
@@ -5,8 +5,10 @@
 
 
 // CHECK-LABEL: sil @simple_reg_promotion
+// CHECK: bb0(%0 : $Int):
+// CHECK-NEXT: return %0 : $Int
 sil @simple_reg_promotion : $@convention(thin) (Int) -> Int {
-bb0(%0 : $Int):                         // CHECK: bb0(%0 : $Int):
+bb0(%0 : $Int):
   %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
   %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
   store %0 to %1a : $*Int
@@ -18,41 +20,32 @@
   strong_release %3 : $<τ_0_0> { var τ_0_0 } <Int>
   strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int>
   return %6 : $Int
-
-  // CHECK-NEXT: return %0 : $Int
 }
 
-
+// Verify that promotion has promoted the tuple load away, and we know that
+// %0 is being returned through scalar instructions in SSA form.
+//
 // CHECK-LABEL: sil @tuple_reg_promotion
+// CHECK: bb0(%0 : $Int):
+// CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ({{.*}} : $Int, {{.*}} : $Int)
+// CHECK-NEXT: [[TUPLE_ELT:%[0-9]+]] = tuple_extract [[TUPLE]] : $(Int, Int), 0
+// CHECK-NEXT: return [[TUPLE_ELT]] : $Int
 sil @tuple_reg_promotion : $@convention(thin) (Int) -> Int {
-bb0(%0 : $Int):                         // CHECK: bb0(%0 : $Int):
+bb0(%0 : $Int):                         
   %1 = alloc_box $<τ_0_0> { var τ_0_0 } <(Int, Int)>
   %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <(Int, Int)>, 0
-
   %a = tuple_element_addr %1a : $*(Int, Int), 0
   %b = tuple_element_addr %1a : $*(Int, Int), 1
   store %0 to %a : $*Int
   store %0 to %b : $*Int
-
   %c = load %1a : $*(Int, Int)
   %d = tuple_extract %c : $(Int, Int), 0
-
   strong_release %1 : $<τ_0_0> { var τ_0_0 } <(Int, Int)>
-
   return %d : $Int
-
-  // Verify that promotion has promoted the tuple load away, and we know that
-  // %0 is being returned through scalar instructions in SSA form.
-  // CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ({{.*}} : $Int, {{.*}} : $Int)
-  // CHECK-NEXT: [[TUPLE_ELT:%[0-9]+]] = tuple_extract [[TUPLE]] : $(Int, Int), 0
-
-  // CHECK-NEXT: return [[TUPLE_ELT]] : $Int
 }
 
-
 sil @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
-
-
+sil @takes_NativeObject_inout : $@convention(thin) (@inout Builtin.NativeObject) -> ()
 
 // Verify that load promotion works properly with inout arguments.
 //
@@ -61,26 +54,32 @@
 //  takes_Int_inout(&a)
 //  return (t, a)
 //}
-// CHECK-LABEL: sil @used_by_inout
+//
+// CHECK-LABEL: sil @used_by_inout : $@convention(thin) (Int) -> (Int, Int) {
+// CHECK: bb0([[ARG:%.*]] : $Int):
 sil @used_by_inout : $@convention(thin) (Int) -> (Int, Int) {
 bb0(%0 : $Int):
   // This alloc_stack can't be removed since it is used by an inout call.
-  // CHECK: %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+  // CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+  // CHECK: [[PB_BOX:%.*]] = project_box [[BOX]]
   %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
   %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
   store %0 to %1a : $*Int
 
   // This load should be eliminated.
+  // CHECK-NOT: load
+  // CHECK: [[FUNC:%.*]] = function_ref @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
+  // CHECK: apply [[FUNC]]([[PB_BOX]])
   %3 = load %1a : $*Int
   %5 = function_ref @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
   %6 = apply %5(%1a) : $@convention(thin) (@inout Int) -> ()
 
   // This load is needed in case the callee modifies the allocation.
-  // CHECK: [[RES:%[0-9]+]] = load
+  // CHECK: [[RES:%[0-9]+]] = load [[PB_BOX]]
   %7 = load %1a : $*Int
 
   // This should use the incoming argument to the function.
-  // CHECK: tuple ({{.*}} : $Int, {{.*}} : $Int)
+  // CHECK: tuple ([[ARG]] : $Int, [[RES]] : $Int)
   %8 = tuple (%3 : $Int, %7 : $Int)
   strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int>
   return %8 : $(Int, Int)
@@ -148,13 +147,75 @@
 
 
 struct ContainsNativeObject {
-  var x : Int
-  var y : Builtin.NativeObject
+  var x : Builtin.NativeObject
+  var y : Int32
+  var z : Builtin.NativeObject
+}
+
+// CHECK-LABEL: sil @multiple_level_extract_1 : $@convention(thin) (@owned ContainsNativeObject) -> Builtin.Int32 {
+// CHECK: bb0([[ARG:%.*]] : $ContainsNativeObject):
+// CHECK:   [[FIELD1:%.*]] = struct_extract [[ARG]] : $ContainsNativeObject, #ContainsNativeObject.y
+// CHECK:   [[FIELD2:%.*]] = struct_extract [[FIELD1]] : $Int32, #Int32._value
+// CHECK:   release_value [[ARG]]
+// CHECK:   return [[FIELD2]]
+// CHECK: } // end sil function 'multiple_level_extract_1'
+sil @multiple_level_extract_1 : $@convention(thin) (@owned ContainsNativeObject) -> Builtin.Int32 {
+bb0(%0 : $ContainsNativeObject):
+  %1 = alloc_stack $ContainsNativeObject
+  store %0 to %1 : $*ContainsNativeObject
+
+  %2 = struct_element_addr %1 : $*ContainsNativeObject, #ContainsNativeObject.y
+  %3 = struct_element_addr %2 : $*Int32, #Int32._value
+  %4 = load %3 : $*Builtin.Int32
+
+  destroy_addr %1 : $*ContainsNativeObject
+  dealloc_stack %1 : $*ContainsNativeObject
+  return %4 : $Builtin.Int32
+}
+
+struct ComplexStruct {
+  var f1 : Builtin.NativeObject
+  var f2 : ContainsNativeObject
+  var f3 : Builtin.Int32
+}
+
+// CHECK-LABEL: sil @multiple_level_extract_2 : $@convention(thin) (@owned ComplexStruct) -> (@owned Builtin.NativeObject, @owned Builtin.NativeObject, Builtin.Int32) {
+// CHECK: bb0([[ARG:%.*]] : $ComplexStruct):
+// CHECK: [[f1:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f3
+// CHECK: [[f2:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f2
+// CHECK: [[f2_x:%.*]] = struct_extract [[f2]] : $ContainsNativeObject, #ContainsNativeObject.x
+// CHECK: [[f3:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f1
+// CHECK-NEXT: strong_retain [[f3]]
+// CHECK-NEXT: strong_retain [[f2_x]]
+// CHECK-NEXT: release_value [[ARG]]
+// CHECK: [[RESULT:%.*]] = tuple ([[f3]] : $Builtin.NativeObject, [[f2_x]] : $Builtin.NativeObject, [[f1]] : $Builtin.Int32)
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function 'multiple_level_extract_2'
+sil @multiple_level_extract_2 : $@convention(thin) (@owned ComplexStruct) -> (@owned Builtin.NativeObject, @owned Builtin.NativeObject, Builtin.Int32) {
+bb0(%0 : $ComplexStruct):
+  %1 = alloc_stack $ComplexStruct
+  store %0 to %1 : $*ComplexStruct
+
+  %2 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f1
+  %3 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f2
+  %4 = struct_element_addr %3 : $*ContainsNativeObject, #ContainsNativeObject.x
+  %5 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f3
+
+  %6 = load %2 : $*Builtin.NativeObject
+  strong_retain %6 : $Builtin.NativeObject
+  %7 = load %4 : $*Builtin.NativeObject
+  strong_retain %7 : $Builtin.NativeObject
+  %8 = load %5 : $*Builtin.Int32
+
+  destroy_addr %1 : $*ComplexStruct
+  dealloc_stack %1 : $*ComplexStruct
+
+  %9 = tuple(%6 : $Builtin.NativeObject, %7 : $Builtin.NativeObject, %8 : $Builtin.Int32)
+  return %9 : $(Builtin.NativeObject, Builtin.NativeObject, Builtin.Int32)
 }
 
 var int_global : Int
 
-
 // CHECK-LABEL: sil @promote_alloc_stack
 sil @promote_alloc_stack : $@convention(thin) (Int32) -> Builtin.Int32 {
 bb0(%0 : $Int32):
@@ -296,8 +357,8 @@
 }
 
 
-// CHECK-LABEL: sil @destroy_addr
-sil @destroy_addr : $@convention(method) (@owned SomeClass) -> @owned SomeClass {
+// CHECK-LABEL: sil @destroy_addr_test
+sil @destroy_addr_test : $@convention(method) (@owned SomeClass) -> @owned SomeClass {
 bb0(%0 : $SomeClass):
   %1 = alloc_stack $SomeClass
   %2 = tuple ()
@@ -416,3 +477,364 @@
   return %r : $Bool
 }
 
+///////////////////
+// Diamond Tests //
+///////////////////
+
+struct NativeObjectPair {
+  var f1: Builtin.NativeObject
+  var f2: Builtin.NativeObject
+}
+
+// These tests ensure that we insert all gep operations, before the stores and
+// any new load operations at the location where the old load was. It also
+// ensures that we are able to handle values that are provided with multilple
+// available values from different stores. Today the tests use the exact same
+// value since pred mem opts is so conservative (it will not support having
+// different available values from different blocks due to the predicate it uses
+// while merging).
+
+// We should just remove the stores here.
+// CHECK-LABEL: sil @diamond_test_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK-NOT: alloc_stack
+// CHECK-NOT: store
+// CHECK-NOT: load
+// CHECK: } // end sil function 'diamond_test_1'
+sil @diamond_test_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+  %1 = alloc_stack $Builtin.NativeObject
+  cond_br undef, bb1, bb2
+
+bb1:
+  store %0 to %1 : $*Builtin.NativeObject
+  br bb3
+
+bb2:
+  store %0 to %1 : $*Builtin.NativeObject
+  br bb3
+
+bb3:
+  %2 = load %1 : $*Builtin.NativeObject
+  strong_retain %2 : $Builtin.NativeObject
+  strong_release %2 : $Builtin.NativeObject
+  dealloc_stack %1 : $*Builtin.NativeObject
+  %9999 = tuple()
+  return %9999 : $()
+}
+
+// This test makes sure that we insert the tuple_extracts that we need before
+// the store in bb0, not at the load block.
+// CHECK-LABEL: sil @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject {
+// CHECK: bb0([[ARG:%.*]] : $NativeObjectPair):
+// CHECK:   [[LHS1:%.*]] = struct_extract [[ARG]] : $NativeObjectPair, #NativeObjectPair.f1
+// CHECK:   [[LHS2:%.*]] = struct_extract [[ARG]] : $NativeObjectPair, #NativeObjectPair.f1
+// CHECK:   cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK:   strong_retain [[LHS2]]
+// CHECK:   br bb3([[LHS2]] :
+//
+// CHECK: bb2:
+// CHECK:   strong_retain [[LHS1]] : $Builtin.NativeObject
+// CHECK:   br bb3([[LHS1]] :
+//
+// CHECK: bb3([[PHI:%.*]] :
+// CHECK:   release_value [[ARG]]
+// CHECK:   return [[PHI]]
+// CHECK: } // end sil function 'diamond_test_2'
+sil @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject {
+bb0(%0 : $NativeObjectPair):
+  %1 = alloc_stack $NativeObjectPair
+  store %0 to %1 : $*NativeObjectPair
+  cond_br undef, bb1, bb2
+
+bb1:
+  %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.f1
+  %3 = load %2 : $*Builtin.NativeObject
+  strong_retain %3 : $Builtin.NativeObject
+  br bb3(%3 : $Builtin.NativeObject)
+
+bb2:
+  %4 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.f1
+  %5 = load %4 : $*Builtin.NativeObject
+  strong_retain %5 : $Builtin.NativeObject
+  br bb3(%5 : $Builtin.NativeObject)
+
+bb3(%6 : $Builtin.NativeObject):
+  destroy_addr %1 : $*NativeObjectPair
+  dealloc_stack %1 : $*NativeObjectPair
+  return %6 : $Builtin.NativeObject
+}
+
+// We should be able to promote all memory operations here.
+//
+// CHECK-LABEL: sil @diamond_test_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
+// CHECK-NOT: alloc_stack
+// CHECK-NOT: load
+// CHECK-NOT: store
+// CHECK: } // end sil function 'diamond_test_3'
+sil @diamond_test_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
+bb0(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject):
+  %2 = alloc_stack $NativeObjectPair
+  %3 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+  %4 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f2
+  store %0 to %3 : $*Builtin.NativeObject
+  store %1 to %4 : $*Builtin.NativeObject
+  cond_br undef, bb1, bb2
+
+bb1:
+  %tup_addr_1 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+  %tup_val_1 = load %tup_addr_1 : $*Builtin.NativeObject
+  strong_retain %tup_val_1 : $Builtin.NativeObject
+  br bb3(%tup_val_1 : $Builtin.NativeObject)
+
+bb2:
+  %tup_addr_2 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+  %tup_val_2 = load %tup_addr_2 : $*Builtin.NativeObject
+  strong_retain %tup_val_2 : $Builtin.NativeObject
+  br bb3(%tup_val_2 : $Builtin.NativeObject)
+
+bb3(%result : $Builtin.NativeObject):
+  destroy_addr %2 : $*NativeObjectPair
+  dealloc_stack %2 : $*NativeObjectPair
+  return %result : $Builtin.NativeObject
+}
+
+struct NativeObjectTriple {
+  var f1: Builtin.NativeObject
+  var f2: NativeObjectPair
+}
+
+// Make sure we insert the struct_extracts in bb1, bb2.
+//
+// CHECK-LABEL: sil @diamond_test_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair) -> @owned Builtin.NativeObject {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair):
+// CHECK:   cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK-NEXT: [[PAIR_LHS:%.*]] = struct_extract [[ARG1]]
+// CHECK-NEXT: br bb3([[PAIR_LHS]] :
+//
+// CHECK: bb2:
+// CHECK-NEXT: [[PAIR_LHS:%.*]] = struct_extract [[ARG1]]
+// CHECK-NEXT: br bb3([[PAIR_LHS]] :
+//
+// CHECK: bb3([[PHI:%.*]] : $Builtin.NativeObject):
+// CHECK-NOT: struct_extract
+// CHECK: strong_retain [[PHI]]
+// CHECK-NOT: struct_extract
+// CHECK: [[REFORMED:%.*]] = struct $NativeObjectTriple ([[ARG0]] : {{.*}}, [[ARG1]] : {{.*}})
+// CHECK-NOT: struct_extract
+// CHECK: release_value [[REFORMED]]
+// CHECK-NOT: struct_extract
+// CHECK: return [[PHI]]
+// CHECK: } // end sil function 'diamond_test_4'
+sil @diamond_test_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair) -> @owned Builtin.NativeObject {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair):
+  %2 = alloc_stack $NativeObjectTriple
+  cond_br undef, bb1, bb2
+
+bb1:
+  %3 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+  %4 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  store %0 to %3 : $*Builtin.NativeObject
+  store %1 to %4 : $*NativeObjectPair
+  br bb3
+
+bb2:
+  %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+  %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  store %0 to %5 : $*Builtin.NativeObject
+  store %1 to %6 : $*NativeObjectPair
+  br bb3
+
+bb3:
+  %11 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  %12 = struct_element_addr %11 : $*NativeObjectPair, #NativeObjectPair.f1
+  %13 = load %12 : $*Builtin.NativeObject
+  strong_retain %13 : $Builtin.NativeObject
+  destroy_addr %2 : $*NativeObjectTriple
+  dealloc_stack %2 : $*NativeObjectTriple
+  return %13 : $Builtin.NativeObject
+}
+
+// Make sure that we do the right thing if our definite init value is partially
+// overridden along one path
+//
+// CHECK-LABEL: sil @diamond_test_5 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair, [[ARG2:%.*]] : $Builtin.NativeObject):
+// CHECK:   [[BOX:%.*]] = alloc_stack $NativeObjectTriple
+// CHECK:   br bb1
+//
+// CHECK: bb1:
+// CHECK:   [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK:   [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK:   store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK:   [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK:   store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK:   cond_br undef, bb2, bb3
+//
+// CHECK: bb2:
+// CHECK:   [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]]
+// CHECK:   store [[ARG2]] to [[TRIPLE_RHS_LHS]]
+// CHECK:   br bb4
+//
+// CHECK: bb3:
+// CHECK:   br bb4
+//
+// CHECK: bb4:
+// CHECK:   [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]] : $*NativeObjectPair, #NativeObjectPair.f1
+// CHECK:   [[TRIPLE_RHS_LHS_VAL:%.*]] = load [[TRIPLE_RHS_LHS]] : $*Builtin.NativeObject
+// CHECK:   [[STRUCT:%.*]] = struct $NativeObjectPair ([[TRIPLE_RHS_LHS_VAL]] : {{.*}}, [[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+// CHECK:   retain_value [[STRUCT]]
+// CHECK:   destroy_addr [[BOX]]
+// CHECK:   return [[STRUCT]]
+// CHECK: } // end sil function 'diamond_test_5'
+sil @diamond_test_5 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair, %arg2 : $Builtin.NativeObject):
+  %2 = alloc_stack $NativeObjectTriple
+  br bb1
+
+bb1:
+  %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+  %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  store %0 to %5 : $*Builtin.NativeObject
+  store %1 to %6 : $*NativeObjectPair
+  cond_br undef, bb2, bb3
+
+bb2:
+  %11 = struct_element_addr %6 : $*NativeObjectPair, #NativeObjectPair.f1
+  store %arg2 to %11 : $*Builtin.NativeObject
+  br bb4
+
+bb3:
+  br bb4
+
+bb4:
+  %13 = load %6 : $*NativeObjectPair
+  retain_value %13 : $NativeObjectPair
+  destroy_addr %2 : $*NativeObjectTriple
+  dealloc_stack %2 : $*NativeObjectTriple
+  return %13 : $NativeObjectPair
+}
+
+// CHECK-LABEL: sil @diamond_test_6 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair, [[ARG2:%.*]] : $Builtin.NativeObject):
+// CHECK:   [[BOX:%.*]] = alloc_stack $NativeObjectTriple
+// CHECK:   cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK:   [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK:   [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK:   store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK:   [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK:   store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK:   cond_br undef, bb3([[TRIPLE_RHS_RHS_VAL]] : {{.*}}), bb4([[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+//
+// CHECK: bb2:
+// CHECK:   [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK:   [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK:   store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK:   [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK:   store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK:   cond_br undef, bb3([[TRIPLE_RHS_RHS_VAL]] : {{.*}}), bb4([[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+//
+// CHECK: bb3([[PHI1:%.*]] : $Builtin.NativeObject):
+// CHECK:   [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK:   [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]]
+// CHECK:   store [[ARG2]] to [[TRIPLE_RHS_LHS]]
+// CHECK:   br bb5([[PHI1:%.*]] : $Builtin.NativeObject)
+//
+// CHECK: bb4([[PHI:%.*]] : $Builtin.NativeObject):
+// CHECK:   br bb5([[PHI]] : {{.*}})
+//
+// CHECK: bb5([[PHI:%.*]] : $Builtin.NativeObject
+// CHECK:   [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK:   [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]] : $*NativeObjectPair, #NativeObjectPair.f1
+// CHECK:   [[TRIPLE_RHS_LHS_VAL:%.*]] = load [[TRIPLE_RHS_LHS]] : $*Builtin.NativeObject
+// CHECK:   [[STRUCT:%.*]] = struct $NativeObjectPair ([[TRIPLE_RHS_LHS_VAL]] : {{.*}}, [[PHI]] : {{.*}})
+// CHECK:   retain_value [[STRUCT]]
+// CHECK:   destroy_addr [[BOX]]
+// CHECK:   return [[STRUCT]]
+// CHECK: } // end sil function 'diamond_test_6'
+sil @diamond_test_6 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair, %arg2 : $Builtin.NativeObject):
+  %2 = alloc_stack $NativeObjectTriple
+  cond_br undef, bb1, bb2
+
+bb1:
+  %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+  %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  store %0 to %5 : $*Builtin.NativeObject
+  store %1 to %6 : $*NativeObjectPair
+  cond_br undef, bb3, bb4
+
+bb2:
+  %7 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+  %8 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  store %0 to %7 : $*Builtin.NativeObject
+  store %1 to %8 : $*NativeObjectPair
+  cond_br undef, bb3, bb4
+
+bb3:
+  %11 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  %12 = struct_element_addr %11 : $*NativeObjectPair, #NativeObjectPair.f1
+  store %arg2 to %12 : $*Builtin.NativeObject
+  br bb5
+
+bb4:
+  br bb5
+
+bb5:
+  %13 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+  %14 = load %13 : $*NativeObjectPair
+  retain_value %14 : $NativeObjectPair
+  destroy_addr %2 : $*NativeObjectTriple
+  dealloc_stack %2 : $*NativeObjectTriple
+  return %14 : $NativeObjectPair
+}
+
+///////////////////////
+// Unreachable Tests //
+///////////////////////
+
+// Make sure that we can handle a dead allocation with a destroy_addr in an
+// unreachable block.
+//
+// TODO: We can support this with trivial changes to canPromoteDestroyAddr. We
+// just need to distinguish a promotion failure around lack of availability vs
+// promotion failure for other reasons.
+//
+//
+// CHECK-LABEL: sil @dead_allocation_with_unreachable_destroy_addr : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
+// CHECK-NEXT: alloc_stack
+// CHECK-NEXT: store
+// CHECK-NEXT: br bb1
+//
+// CHECK: bb1:
+// CHECK-NEXT: destroy_addr
+// CHECK-NEXT: dealloc_stack
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+//
+// CHECK: bb2:
+// CHECK-NEXT: destroy_addr
+// CHECK-NEXT: unreachable
+// CHECK: } // end sil function 'dead_allocation_with_unreachable_destroy_addr'
+sil @dead_allocation_with_unreachable_destroy_addr : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+  %1 = alloc_stack $Builtin.NativeObject
+  store %0 to %1 : $*Builtin.NativeObject
+  br bb1
+
+bb1:
+  destroy_addr %1 : $*Builtin.NativeObject
+  dealloc_stack %1 : $*Builtin.NativeObject
+  %9999 = tuple()
+  return %9999 : $()
+
+bb2:
+  destroy_addr %1 : $*Builtin.NativeObject
+  unreachable
+}
\ No newline at end of file
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index cc08acb..9751347 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -463,3 +463,59 @@
   apply %closure() : $@callee_guaranteed () -> ()
   return %closure : $@callee_guaranteed () -> ()
 }
+
+sil @guaranteed_closure_throws : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+
+// CHECK: sil @test_guaranteed_closure_try_apply
+// CHECK: bb0(%0 : $C, %1 : $Builtin.Int32):
+// CHECK:   strong_retain %0 : $C
+// CHECK:   [[FUN:%.*]] = function_ref @guaranteed_closure_throws
+// CHECK:   [[CL:%.*]] = partial_apply [callee_guaranteed] [[FUN]](%1)
+// CHECK:   try_apply [[FUN]](%0, %1)
+// CHECK: bb1({{.*}}):
+// CHECK-NOT:   strong_release
+// CHECK:   br bb3
+// CHECK: bb2({{.*}}):
+// CHECK-NOT:   strong_release
+// CHECK:   br bb3
+// CHECK: bb3:
+// CHECK:   return [[CL]]
+
+sil @test_guaranteed_closure_try_apply : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @owned @callee_guaranteed (@guaranteed C) -> @error Error {
+bb0(%0: $C, %1: $Builtin.Int32):
+  strong_retain %0 : $C
+  %closure_fun = function_ref @guaranteed_closure_throws : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+  %closure = partial_apply [callee_guaranteed] %closure_fun(%1) : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+  try_apply %closure(%0) : $@callee_guaranteed (@guaranteed C) -> @error Error, normal bb7, error bb11
+
+bb7(%callret : $()):
+  br bb99
+
+bb11(%128 : $Error):
+  br bb99
+
+bb99:
+  return %closure : $@callee_guaranteed (@guaranteed C) -> @error Error
+}
+
+// Make sure convert_function -> apply does the right thing with metatypes
+class Base {}
+class Derived {}
+
+sil @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+
+// CHECK-LABEL: sil @passesMetatype
+// CHECK: [[METATYPE:%.*]] = metatype $@thick Derived.Type
+// CHECK: [[FN:%.*]] = function_ref @takesMetatype
+// CHECK: [[CONVERTED:%.*]] = unchecked_trivial_bit_cast [[METATYPE]] : $@thick Derived.Type to $@thick Base.Type
+// CHECK: [[RESULT:%.*]] = apply [[FN]]([[CONVERTED]])
+
+sil @passesMetatype : $@convention(thin) () -> () {
+bb0:
+  %metatype = metatype $@thick Derived.Type
+  %fn = function_ref @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+  %converted = convert_function %fn : $@convention(thin) (@thick Base.Type) -> () to $@convention(thin) (@thick Derived.Type) -> ()
+  %result = apply %converted(%metatype) : $@convention(thin) (@thick Derived.Type) -> ()
+  %return = tuple ()
+  return %return : $()
+}
diff --git a/test/Sema/accessibility.swift b/test/Sema/accessibility.swift
index 36864f6..65a49c2 100644
--- a/test/Sema/accessibility.swift
+++ b/test/Sema/accessibility.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -swift-version 5
 
 public protocol PublicProto {
   func publicReq()
@@ -426,6 +426,25 @@
 class DefaultSubclassInternal : InternalClass {}
 class DefaultSubclassPrivate : PrivateClass {} // expected-error {{class must be declared private or fileprivate because its superclass is private}}
 
+public class PublicGenericClass<T> {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalGenericClass<T> {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateGenericClass<T> {}
+
+open class OpenConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<Int>' of open class must be open}}
+public class PublicConcreteSubclassPublic : PublicGenericClass<Int> {}
+public class PublicConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicConcreteSubclassPrivate : PrivateGenericClass<Int> {} // expected-error {{class cannot be declared public because its superclass is private}}
+public class PublicConcreteSubclassPublicPrivateArg : PublicGenericClass<PrivateStruct> {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+open class OpenGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<T>' of open class must be open}}
+public class PublicGenericSubclassPublic<T> : PublicGenericClass<T> {}
+public class PublicGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicGenericSubclassPrivate<T> : PrivateGenericClass<T> {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+
 
 public enum PublicEnumPrivate {
   case A(PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
@@ -647,3 +666,24 @@
     fileprivate typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-16=internal}}
   }
 }
+
+internal typealias InternalComposition = PublicClass & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalComposition : InternalComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+internal typealias InternalGenericComposition<T> = PublicGenericClass<T> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalGenericComposition : InternalGenericComposition<Int> { // expected-error {{class cannot be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+internal typealias InternalConcreteGenericComposition = PublicGenericClass<Int> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalConcreteGenericComposition : InternalConcreteGenericComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+  public func publicReq() {}
+}
+
+public typealias BadPublicComposition1 = InternalClass & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition2 = PublicClass & InternalProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition3<T> = InternalGenericClass<T> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition4 = InternalGenericClass<Int> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition5 = PublicGenericClass<InternalStruct> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
diff --git a/test/Sema/diag_erroneous_iuo.swift b/test/Sema/diag_erroneous_iuo.swift
index 2e51057..d938be6 100644
--- a/test/Sema/diag_erroneous_iuo.swift
+++ b/test/Sema/diag_erroneous_iuo.swift
@@ -81,6 +81,8 @@
 
   var x: V
   var y: W
+  var fn1: (Int!) -> Int // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  var fn2: (Int) -> Int! // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
 
   subscript (
     index: ImplicitlyUnwrappedOptional<Int> // expected-error {{the spelling 'ImplicitlyUnwrappedOptional' is unsupported; use '!' after the type name}}{{12-40=}}{{43-43=!}}{{43-44=}}
@@ -138,18 +140,53 @@
 func vararg(_ first: Int, more: Int!...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
 }
 
+func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+}
+
 func iuoInTuple() -> (Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
   return 1
 }
 
-func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
   return 1
 }
 
+func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return (1.0, 1)
+}
+
+func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return (1.0, 1)
+}
+
 func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
   return fn(0)
 }
 
+func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return fn(0)
+}
+
+func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return fn(0)
+}
+
+func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return fn(0)
+}
+
 func returnsFunc() -> (Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
   return { $0 }
 }
+
+func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return { $0 }
+}
+
+func returnsFunc2() -> (Int) -> Int! { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return { $0 }
+}
+
+func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+  return { $0 }
+}
diff --git a/test/Sema/enum_equatable_hashable.swift b/test/Sema/enum_equatable_hashable.swift
index b5c334d..a915449 100644
--- a/test/Sema/enum_equatable_hashable.swift
+++ b/test/Sema/enum_equatable_hashable.swift
@@ -226,6 +226,18 @@
   case end(Int)
 }
 
+// Check the use of conditional conformances.
+enum ArrayOfEquatables : Equatable {
+case only([Int])
+}
+
+struct NotEquatable { }
+
+// FIXME: rdar://problem/35518088 this should fail.
+enum ArrayOfNotEquatables : Equatable {
+case only([NotEquatable])
+}
+
 // FIXME: Remove -verify-ignore-unknown.
 // <unknown>:0: error: unexpected error produced: invalid redeclaration of 'hashValue'
 // <unknown>:0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool'
diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift
index 138f9a9..9793e58 100644
--- a/test/Sema/enum_raw_representable.swift
+++ b/test/Sema/enum_raw_representable.swift
@@ -78,8 +78,6 @@
   let a: Int = E.a // expected-error {{cannot convert value of type 'Outer.E' to specified type 'Int'}}
 
   enum E : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
-  // expected-error@-1 {{'Outer.E' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
-  // expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
     case a
   }
 }
@@ -146,3 +144,10 @@
   let _ = choice == "bar"
   // expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}}
 }
+
+
+struct NotEquatable { }
+
+enum ArrayOfNewEquatable : Array<NotEquatable> { }
+// expected-error@-1{{raw type 'Array<NotEquatable>' is not expressible by any literal}}
+// expected-error@-2{{'ArrayOfNewEquatable' declares raw type 'Array<NotEquatable>', but does not conform to RawRepresentable and conformance could not be synthesized}}
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 3e8cbdd..60104ea 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -920,6 +920,27 @@
   return %2 : $()
 }
 
+// CHECK-LABEL: [Onone] @test_onone : $@convention(thin) () -> ()
+sil [serialized] [Onone] @test_onone : $@convention(thin) () -> () {
+bb0:
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: [Ospeed] @test_ospeed : $@convention(thin) () -> ()
+sil [serialized] [Ospeed] @test_ospeed : $@convention(thin) () -> () {
+bb0:
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: [Osize] @test_osize : $@convention(thin) () -> ()
+sil [serialized] [Osize] @test_osize : $@convention(thin) () -> () {
+bb0:
+  %2 = tuple ()
+  return %2 : $()
+}
+
 sil [serialized] @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int
 
 sil [serialized] @takes_int64_float32 : $@convention(thin) (Int, Float32) -> ()
@@ -1420,6 +1441,9 @@
   %130 = function_ref @noinline_callee : $@convention(thin) () -> Int
   %132 = function_ref @always_inline_callee : $@convention(thin) () -> Int
   %131 = function_ref @test_semantics : $@convention(thin) () -> ()
+  %136 = function_ref @test_onone : $@convention(thin) () -> ()
+  %137 = function_ref @test_ospeed : $@convention(thin) () -> ()
+  %138 = function_ref @test_osize : $@convention(thin) () -> ()
   %111 = function_ref @test_partial_apply : $@convention(thin) Float32 -> @callee_owned Int -> ()
   %113 = function_ref @test_dynamic_lookup_br : $@convention(thin) (AnyObject) -> ()
   %115 = function_ref @test_mark_fn_escape : $@convention(thin) () -> ()
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
index 7bf9c7a..6eaf68c 100644
--- a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
+++ b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
@@ -115,3 +115,22 @@
 //- (nonnull instancetype)initWithValue:(long)value;
 #endif
 @end
+
+
+#if !BAD
+struct BoxedInt {
+  int value;
+};
+#endif
+
+@interface MethodWithDisappearingType : Object
+#if !BAD
+- (struct BoxedInt)boxItUp;
+#endif
+@end
+
+@interface InitializerWithDisappearingType : Object
+#if !BAD
+- (nonnull instancetype)initWithBoxedInt:(struct BoxedInt)box;
+#endif
+@end
diff --git a/test/Serialization/Recovery/overrides.swift b/test/Serialization/Recovery/overrides.swift
index c0b7b25..486f6c0 100644
--- a/test/Serialization/Recovery/overrides.swift
+++ b/test/Serialization/Recovery/overrides.swift
@@ -311,4 +311,33 @@
 // CHECK-RECOVERY-NEXT: /* placeholder for init(value:) */
 // CHECK-RECOVERY-NEXT: {{^}$}}
 
+public class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+  public override func boxItUp() -> BoxedInt { fatalError() }
+}
+
+// CHECK-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-NEXT: override func boxItUp() -> BoxedInt
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
+public class E2_InitializerStub : InitializerWithDisappearingType {
+  public init(unrelatedValue: Int) { fatalError() }
+}
+
+// CHECK-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-NEXT: init(unrelatedValue: Int)
+// CHECK-NEXT: init(boxedInt box: BoxedInt)
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init(unrelatedValue: Int)
+// CHECK-RECOVERY-NEXT: /* placeholder for init(boxedInt:) */
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
 #endif // TEST
diff --git a/test/Serialization/function.swift b/test/Serialization/function.swift
index 5b3b69a..9a12e9a 100644
--- a/test/Serialization/function.swift
+++ b/test/Serialization/function.swift
@@ -35,18 +35,18 @@
 // SIL:   {{%.+}} = apply [[USE_NESTED]]({{%.+}}, {{%.+}}, {{%.+}}) : $@convention(thin) (Int, Int, Int) -> ()
 useNested((raw, raw2), n: raw3)
 
-// SIL:   [[VARIADIC:%.+]] = function_ref @_T08def_func8variadicySd1x_SidtF : $@convention(thin) (Double, @owned Array<Int>) -> ()
 // SIL:   [[VA_SIZE:%.+]] = integer_literal $Builtin.Word, 2
 // SIL:   {{%.+}} = apply {{%.*}}<Int>([[VA_SIZE]])
+// SIL:   [[VARIADIC:%.+]] = function_ref @_T08def_func8variadicySd1x_SidtF : $@convention(thin) (Double, @owned Array<Int>) -> ()
 // SIL:   {{%.+}} = apply [[VARIADIC]]({{%.+}}, {{%.+}}) : $@convention(thin) (Double, @owned Array<Int>) -> ()
 variadic(x: 2.5, 4, 5)
 
 // SIL:   [[VARIADIC:%.+]] = function_ref @_T08def_func9variadic2ySid_Sd1xtF : $@convention(thin) (@owned Array<Int>, Double) -> ()
 variadic2(1, 2, 3, x: 5.0)
 
-// SIL:   [[SLICE:%.+]] = function_ref @_T08def_func5sliceySaySiG1x_tF : $@convention(thin) (@owned Array<Int>) -> ()
 // SIL:   [[SLICE_SIZE:%.+]] = integer_literal $Builtin.Word, 3
 // SIL:   {{%.+}} = apply {{%.*}}<Int>([[SLICE_SIZE]])
+// SIL:   [[SLICE:%.+]] = function_ref @_T08def_func5sliceySaySiG1x_tF : $@convention(thin) (@owned Array<Int>) -> ()
 // SIL:   {{%.+}} = apply [[SLICE]]({{%.+}}) : $@convention(thin) (@owned Array<Int>) -> ()
 slice(x: [2, 4, 5])
 
diff --git a/test/Serialization/inherited-initializer.swift b/test/Serialization/inherited-initializer.swift
index 7042b69..b2936f3 100644
--- a/test/Serialization/inherited-initializer.swift
+++ b/test/Serialization/inherited-initializer.swift
@@ -8,15 +8,15 @@
 
 // CHECK-LABEL: sil hidden @_T04main10testSimpleyyF
 func testSimple() {
-  // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
   // CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase0C0CACSicfcfA_
   // CHECK: [[ARG:%.+]] = apply [[DEFAULT]]()
+  // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
   // CHECK: apply [[INIT]]([[ARG]], {{%.+}})
   _ = InheritsInit()
 
-  // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
   // CHECK: [[VALUE:%.+]] = integer_literal $Builtin.Int2048, 5
   // CHECK: [[ARG:%.+]] = apply {{%.+}}([[VALUE]], {{%.+}}) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+  // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
   // CHECK: apply [[INIT]]([[ARG]], {{%.+}})
   _ = InheritsInit(5)
 } // CHECK: end sil function '_T04main10testSimpleyyF'
@@ -31,24 +31,24 @@
 
 // CHECK-LABEL: sil hidden @_T04main11testGenericyyF
 func testGeneric() {
-  // CHECK: [[INIT:%.+]] = function_ref @_T04main10GenericSubCACyxGxcfC
   // CHECK: [[TYPE:%.+]] = metatype $@thick GenericSub<Reinitializable<Int8>>.Type
   // CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
   // CHECK: apply [[DEFAULT]]<Reinitializable<Int8>>({{%.+}})
+  // CHECK: [[INIT:%.+]] = function_ref @_T04main10GenericSubCACyxGxcfC
   // CHECK: apply [[INIT]]<Reinitializable<Int8>>({{%.+}}, [[TYPE]])
   _ = GenericSub<Reinitializable<Int8>>.init() // works around SR-3806
 
-  // CHECK: [[INIT:%.+]] = function_ref @_T04main18ModifiedGenericSubCACyxGAA15ReinitializableVyxGcfC
   // CHECK: [[TYPE:%.+]] = metatype $@thick ModifiedGenericSub<Int16>.Type
   // CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
   // CHECK: apply [[DEFAULT]]<Reinitializable<Int16>>({{%.+}})
+  // CHECK: [[INIT:%.+]] = function_ref @_T04main18ModifiedGenericSubCACyxGAA15ReinitializableVyxGcfC
   // CHECK: apply [[INIT]]<Int16>({{%.+}}, [[TYPE]])
   _ = ModifiedGenericSub<Int16>()
 
-  // CHECK: [[INIT:%.+]] = function_ref @_T04main13NonGenericSubCAcA15ReinitializableVySiGcfC
   // CHECK: [[TYPE:%.+]] = metatype $@thick NonGenericSub.Type
   // CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
   // CHECK: apply [[DEFAULT]]<Reinitializable<Int>>({{%.+}})
+  // CHECK: [[INIT:%.+]] = function_ref @_T04main13NonGenericSubCAcA15ReinitializableVySiGcfC
   // CHECK: apply [[INIT]]({{%.+}}, [[TYPE]])
   _ = NonGenericSub()
 } // CHECK: end sil function '_T04main11testGenericyyF'
diff --git a/test/Serialization/objc.swift b/test/Serialization/objc.swift
index 92684b1..85e07af 100644
--- a/test/Serialization/objc.swift
+++ b/test/Serialization/objc.swift
@@ -18,7 +18,7 @@
   // SIL: = objc_method %{{.+}} : $ObjCClass, #ObjCClass.implicitlyObjC!1.foreign
   obj.implicitlyObjC()
 
-  // SIL: = objc_method %{{.+}} : $@thick ObjCClass.Type, #ObjCClass.classMethod!1.foreign
+  // SIL: = objc_method %{{.+}} : $@objc_metatype ObjCClass.Type, #ObjCClass.classMethod!1.foreign
   ObjCClass.classMethod()
 }
 
diff --git a/test/Serialization/serialize_attr.swift b/test/Serialization/serialize_attr.swift
index a062448..0fc5004 100644
--- a/test/Serialization/serialize_attr.swift
+++ b/test/Serialization/serialize_attr.swift
@@ -13,6 +13,27 @@
 @_versioned
 @_semantics("crazy") func foo() -> Int  { return 5}
 
+// @_optimize
+// -----------------------------------------------------------------------------
+
+//CHECK-DAG: @_optimize(none) func test_onone()
+@_inlineable
+@_versioned
+@_optimize(none)
+func test_onone() -> Int  { return 5}
+
+//CHECK-DAG: @_optimize(speed) func test_ospeed()
+@_inlineable
+@_versioned
+@_optimize(speed)
+func test_ospeed() -> Int  { return 5}
+ 
+//CHECK-DAG: @_optimize(size) func test_osize()
+@_inlineable
+@_versioned
+@_optimize(size)
+func test_osize() -> Int  { return 5}
+
 // @_specialize
 // -----------------------------------------------------------------------------
 
diff --git a/test/SourceKit/Indexing/index_swift_lib.swift b/test/SourceKit/Indexing/index_swift_lib.swift
deleted file mode 100644
index 16f52a2..0000000
--- a/test/SourceKit/Indexing/index_swift_lib.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-// REQUIRES: FIXME
-
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Swift.swiftmodule -- %mcp_opt > %t.txt
-// RUN: %FileCheck %s -input-file %t.txt
-
-// CHECK:      key.name: "Dictionary",
-// CHECK-NEXT: key.usr: "s:Vs10Dictionary",
-
-// RUN: %FileCheck %s -input-file %t.txt -check-prefix=CHECK-INTERNAL
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Foundation.swiftmodule -- %clang-importer-sdk %mcp_opt > %t.foundation.txt
-// RUN: %FileCheck %s -input-file %t.foundation.txt -check-prefix=CHECK-FOUNDATION
-
-// CHECK-INTERNAL-NOT: key.name: "_bridgeToObjectiveCUnconditional",
-
-// CHECK-FOUNDATION-NOT: _convertStringToNSString
diff --git a/test/SourceKit/Misc/ignore_bridging_pch.swift b/test/SourceKit/Misc/ignore_bridging_pch.swift
deleted file mode 100644
index b2c9812..0000000
--- a/test/SourceKit/Misc/ignore_bridging_pch.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -enable-bridging-pch %s | %FileCheck %s
-// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -disable-bridging-pch %s | %FileCheck %s
-
-var s = 10
-s.
-
-// CHECK: littleEndian
diff --git a/test/SourceKit/Misc/ignored-flags.swift b/test/SourceKit/Misc/ignored-flags.swift
new file mode 100644
index 0000000..9e7b437
--- /dev/null
+++ b/test/SourceKit/Misc/ignored-flags.swift
@@ -0,0 +1,11 @@
+var s = 10
+s.
+
+// CHECK: littleEndian
+
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -j4 %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -c %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -v %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -embed-bitcode %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -enable-bridging-pch %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -disable-bridging-pch %s | %FileCheck %s
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index 6c36768..3eb5364 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -1,19 +1,43 @@
-<UnknownDecl>// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
+// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
 // RUN: diff -u %s %t
 // RUN: %swift-syntax-test -input-source-filename %s -parse-gen -print-node-kind > %t.withkinds
 // RUN: diff -u %S/Outputs/round_trip_parse_gen.swift.withkinds %t.withkinds
 
-class C {<UnknownDecl>
-  func bar(_ a: Int) <CodeBlock>{}</CodeBlock></UnknownDecl><UnknownDecl>
-  func bar1(_ a: Float) -> Float <CodeBlock>{ <UnknownStmt>return <UnknownExpr><FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr></UnknownExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
-  func foo() <CodeBlock>{<UnknownDecl>
-    var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr></UnknownDecl><UnknownDecl>
-    var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr></UnknownDecl><UnknownExpr>
-    bar(<IntegerLiteralExpr>1</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
-    bar(<IntegerLiteralExpr>+10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
-    bar(<IntegerLiteralExpr>-10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
-    bar1(<FloatLiteralExpr>-1.1</FloatLiteralExpr>)</UnknownExpr><UnknownExpr>
-    bar1(<FloatLiteralExpr>1.1</FloatLiteralExpr>)</UnknownExpr><UnknownDecl>
-    var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl>
-  }</CodeBlock></UnknownDecl>
-}</UnknownDecl>
+class C {
+  func bar(_ a: Int) <CodeBlock>{}</CodeBlock>
+  func bar1(_ a: Float) -> Float <CodeBlock>{ return <FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr>}</CodeBlock>
+  func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+  func bar3(a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+  func bar4(_ a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+  func foo() <CodeBlock>{
+    var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr>
+    var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr><IdentifierExpr>
+    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)
+    var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr><IdentifierExpr>
+    foo</IdentifierExpr>()
+  }</CodeBlock>
+
+  func foo1() <CodeBlock>{<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>), </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</DictionaryElement>]</DictionaryExpr><IdentifierExpr>
+    foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)
+  }</CodeBlock>
+  func boolAnd() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>&& <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+  func boolOr() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>|| <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+
+  func foo2() <CodeBlock>{<DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr>= <TernaryExpr>(<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) ? (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) : (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>)</TernaryExpr>
+  }</CodeBlock>
+}
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 839126a..a9d72bb 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -6,6 +6,9 @@
 class C {
   func bar(_ a: Int) {}
   func bar1(_ a: Float) -> Float { return -0.6 + 0.1 - 0.3 }
+  func bar2(a: Int, b: Int, c:Int) -> Int { return 1 }
+  func bar3(a: Int) -> Int { return 1 }
+  func bar4(_ a: Int) -> Int { return 1 }
   func foo() {
     var a = /*comment*/"abc"/*comment*/
     var b = /*comment*/+2/*comment*/
@@ -15,5 +18,26 @@
     bar1(-1.1)
     bar1(1.1)
     var f = /*comments*/+0.1/*comments*/
+    foo()
+  }
+
+  func foo1() {
+    _ = bar2(a:1, b:2, c:2)
+    _ = bar2(a:1 + 1, b:2 * 2 + 2, c:2 + 2)
+    _ = bar2(a : bar2(a: 1, b: 2, c: 3), b: 2, c: 3)
+    _ = bar3(a : bar3(a: bar3(a: 1)))
+    _ = bar4(bar4(bar4(1)))
+    _ = [1, 2, 3, 4]
+    _ = [1:1, 2:2, 3:3, 4:4]
+    _ = [bar3(a:1), bar3(a:1), bar3(a:1), bar3(a:1)]
+    _ = ["a": bar3(a:1), "b": bar3(a:1), "c": bar3(a:1), "d": bar3(a:1)]
+    foo(nil, nil, nil)
+  }
+  func boolAnd() -> Bool { return true && false }
+  func boolOr() -> Bool { return true || false }
+
+  func foo2() {
+    _ = true ? 1 : 0
+    _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0)
   }
 }
diff --git a/test/attr/attr_availability_transitive_ios.swift b/test/attr/attr_availability_transitive_ios.swift
new file mode 100644
index 0000000..8ed79a0
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {}
+
+func call_ios_extension() {
+    ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+func call_ios() {
+    ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+    ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+    ios() // OK; same
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+    ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+    ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_ios_extension.swift b/test/attr/attr_availability_transitive_ios_extension.swift
new file mode 100644
index 0000000..6f73286
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {} // expected-note 2{{'ios_extension()' has been explicitly marked unavailable here}}
+
+func call_ios_extension() {
+    ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+func call_ios() {
+    ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+    ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+    ios()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+    ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+    ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_multiple.swift b/test/attr/attr_availability_transitive_multiple.swift
new file mode 100644
index 0000000..8ef579d
--- /dev/null
+++ b/test/attr/attr_availability_transitive_multiple.swift
@@ -0,0 +1,18 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Check that only the platform we are compiling for is considered when allowing access to unavailable declarations.
+
+@available(iOS, unavailable)
+@available(OSX, unavailable)
+func unavailable() {} // expected-note {{'unavailable()' has been explicitly marked unavailable here}}
+
+@available(iOS, unavailable)
+func call_with_ios_unavailable() {
+	unavailable() // expected-error {{'unavailable()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func call_with_osx_unavailable() {
+	unavailable() // OK: same
+}
diff --git a/test/attr/attr_availability_transitive_nested.swift b/test/attr/attr_availability_transitive_nested.swift
new file mode 100644
index 0000000..7d8b474
--- /dev/null
+++ b/test/attr/attr_availability_transitive_nested.swift
@@ -0,0 +1,25 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Make sure that a compatible unavailable wrapping doesn't allow referencing declarations that are completely unavailable.
+
+@available(iOS, unavailable)
+class Outer {
+  @available(*, unavailable)
+  func completelyBadMethod() {} // expected-note {{'completelyBadMethod()' has been explicitly marked unavailable here}}
+}
+
+@available(iOS, unavailable)
+func test(outer: Outer) {
+  outer.completelyBadMethod() // expected-error {{'completelyBadMethod()' is unavailable}}
+}
+
+@available(*, unavailable)
+class Outer2 { // expected-note {{'Outer2' has been explicitly marked unavailable here}}
+	@available(iOS, unavailable)
+    func innerUnavailable() {}
+}
+@available(iOS, unavailable)
+func test2(outer: Outer2) { // expected-error {{'Outer2' is unavailable}}
+  outer.innerUnavailable()
+}
diff --git a/test/attr/attr_availability_transitive_osx.swift b/test/attr/attr_availability_transitive_osx.swift
new file mode 100644
index 0000000..eadaf60
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {}
+
+func call_osx_extension() {
+    osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+func call_osx() {
+    osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+    osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+    osx() // OK; same
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+    osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+    osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_osx_extension.swift b/test/attr/attr_availability_transitive_osx_extension.swift
new file mode 100644
index 0000000..949ef68
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {} // expected-note 2{{'osx_extension()' has been explicitly marked unavailable here}}
+
+func call_osx_extension() {
+    osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+func call_osx() {
+    osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+    osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+    osx()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+    osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+    osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/attr/attr_inlineable.swift b/test/attr/attr_inlineable.swift
index d675917..4dc3a491 100644
--- a/test/attr/attr_inlineable.swift
+++ b/test/attr/attr_inlineable.swift
@@ -24,10 +24,10 @@
   public init() {}
 
   @_inlineable public var storedProperty: Int
-  // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+  // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
 
   @_inlineable public lazy var lazyProperty: Int = 0
-  // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+  // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
 }
 
 public struct Struct {
diff --git a/test/attr/attributes.swift b/test/attr/attributes.swift
index 966ae39..993b5fe 100644
--- a/test/attr/attributes.swift
+++ b/test/attr/attributes.swift
@@ -215,6 +215,11 @@
 @inline(__always) class FooClass2 { // expected-error {{@inline(__always) cannot be applied to this declaration}} {{1-19=}}
 }
 
+@_optimize(speed) func OspeedFunc() {}
+@_optimize(speed) var OpeedVar : Int // expected-error {{@_optimize(speed) cannot be applied to stored properties}} {{1-19=}}
+@_optimize(speed) class OspeedClass { // expected-error {{@_optimize(speed) cannot be applied to this declaration}} {{1-19=}}
+}
+
 class A {
   @inline(never) init(a : Int) {}
   var b : Int {
@@ -237,6 +242,18 @@
   }
 }
 
+class C {
+  @_optimize(speed) init(a : Int) {}
+  var b : Int {
+    @_optimize(none) get {
+      return 42
+    }
+    @_optimize(size) set {
+    }
+  }
+  @_optimize(size) var c : Int // expected-error {{@_optimize(size) cannot be applied to stored properties}}
+}
+
 class SILStored {
   @sil_stored var x : Int = 42  // expected-error {{'sil_stored' only allowed in SIL modules}}
 }
diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift
index 117a0b5..36af2df 100644
--- a/test/decl/ext/protocol.swift
+++ b/test/decl/ext/protocol.swift
@@ -959,3 +959,43 @@
 extension A & B { // okay
 
 }
+
+// Suppress near-miss warning for unlabeled initializers.
+protocol P9 {
+  init(_: Int)
+  init(_: Double)
+}
+
+extension P9 {
+  init(_ i: Int) {
+    self.init(Double(i))
+  }
+}
+
+struct X9 : P9 {
+  init(_: Float) { }
+}
+
+extension X9 {
+  init(_: Double) { }
+}
+
+// Suppress near-miss warning for unlabeled subscripts.
+protocol P10 {
+  subscript (_: Int) -> Int { get }
+  subscript (_: Double) -> Double { get }
+}
+
+extension P10 {
+  subscript(i: Int) -> Int {
+    return Int(self[Double(i)])
+  }
+}
+
+struct X10 : P10 {
+  subscript(f: Float) -> Float { return f }
+}
+
+extension X10 {
+  subscript(d: Double) -> Double { return d }
+}
diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift
index 066556c..2498292 100644
--- a/test/expr/unary/keypath/keypath.swift
+++ b/test/expr/unary/keypath/keypath.swift
@@ -269,7 +269,10 @@
   subscript(keyPath kp: PartialKeyPath<ZwithSubscript>) -> Any { return 0 }
 }
 
+struct NotZ {}
+
 func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript,
+                          wrongType: inout NotZ,
                           kp: KeyPath<ZwithSubscript, Int>,
                           wkp: WritableKeyPath<ZwithSubscript, Int>,
                           rkp: ReferenceWritableKeyPath<ZwithSubscript, Int>) {
@@ -312,6 +315,12 @@
   readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}}
   // FIXME: silently falls back to keypath application, which seems inconsistent
   writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}}
+
+  _ = wrongType[keyPath: kp] // expected-error{{cannot be applied}}
+  _ = wrongType[keyPath: wkp] // expected-error{{cannot be applied}}
+  _ = wrongType[keyPath: rkp] // expected-error{{cannot be applied}}
+  _ = wrongType[keyPath: pkp] // expected-error{{cannot be applied}}
+  _ = wrongType[keyPath: akp]
 }
 
 func testKeyPathSubscriptMetatype(readonly: Z.Type, writable: inout Z.Type,
@@ -358,10 +367,33 @@
   _ = base[keyPath: kp]
 }
 
-func testKeyPathSubscriptExistentialBase(base: B, kp: KeyPath<P, String>) {
-  _ = base[keyPath: kp]
-}
+func testKeyPathSubscriptExistentialBase(concreteBase: inout B,
+                                     existentialBase: inout P,
+                                     kp: KeyPath<P, String>,
+                                     wkp: WritableKeyPath<P, String>,
+                                     rkp: ReferenceWritableKeyPath<P, String>,
+                                     pkp: PartialKeyPath<P>,
+                                     s: String) {
+  _ = concreteBase[keyPath: kp]
+  _ = concreteBase[keyPath: wkp]
+  _ = concreteBase[keyPath: rkp]
+  _ = concreteBase[keyPath: pkp]
 
+  concreteBase[keyPath: kp] = s // expected-error{{}}
+  concreteBase[keyPath: wkp] = s // expected-error{{}}
+  concreteBase[keyPath: rkp] = s
+  concreteBase[keyPath: pkp] = s // expected-error{{}}
+
+  _ = existentialBase[keyPath: kp]
+  _ = existentialBase[keyPath: wkp]
+  _ = existentialBase[keyPath: rkp]
+  _ = existentialBase[keyPath: pkp]
+
+  existentialBase[keyPath: kp] = s // expected-error{{}}
+  existentialBase[keyPath: wkp] = s
+  existentialBase[keyPath: rkp] = s
+  existentialBase[keyPath: pkp] = s // expected-error{{}}
+}
 
 struct AA {
   subscript(x: Int) -> Int { return x }
diff --git a/test/expr/unary/keypath/salvage-with-other-type-errors.swift b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
index e035613..7a6af78 100644
--- a/test/expr/unary/keypath/salvage-with-other-type-errors.swift
+++ b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
@@ -52,6 +52,7 @@
 extension Bindable {
   func test<Value>(to targetKeyPath: ReferenceWritableKeyPath<Self, Value>, change: Value?) {
     if self[keyPath:targetKeyPath] != change {  // expected-error{{}}
+      // expected-note@-1{{overloads for '!=' exist with these partially matching parameter lists: (Self, Self), (_OptionalNilComparisonType, Wrapped?)}}
       self[keyPath: targetKeyPath] = change!
     }
   }
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
index 127d1cf..7b7a468 100644
--- a/test/expr/unary/selector/selector.swift
+++ b/test/expr/unary/selector/selector.swift
@@ -134,7 +134,7 @@
 }
 
 switch optionalSel {
-case #selector(SR1827.bar): // expected-error{{expression pattern of type 'Selector' cannot match values of type 'Selector?'}} {{27-27=?}}
+case #selector(SR1827.bar):
   break
 case #selector(SR1827.bar)!: // expected-error{{cannot force unwrap value of non-optional type 'Selector'}}
   break
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected
new file mode 100644
index 0000000..4f6768a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+  
+
+  func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+extension Foo {
+/// This is just some documentation
+  func methodWithoutParameters() {
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  var computedVariable: Int {
+    return 0
+  }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected
new file mode 100644
index 0000000..b28cecb
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+  /// This is just some documentation
+  func methodWithoutParameters() {
+  }
+
+  func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  
+}
+
+extension OtherClass {
+var computedVariable: Int {
+    return 0
+  }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected
new file mode 100644
index 0000000..6606d15
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+  
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+extension Foo {
+/// This is just some documentation
+  func methodWithoutParameters() {
+  }
+
+  func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  var computedVariable: Int {
+    return 0
+  }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected
new file mode 100644
index 0000000..4f6768a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+  
+
+  func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+extension Foo {
+/// This is just some documentation
+  func methodWithoutParameters() {
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  var computedVariable: Int {
+    return 0
+  }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected
new file mode 100644
index 0000000..5d2b19a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+  /// This is just some documentation
+  func methodWithoutParameters() {
+  }
+
+  
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+extension Foo {
+func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  var computedVariable: Int {
+    return 0
+  }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/basic.swift b/test/refactoring/MoveMembersToExtension/basic.swift
new file mode 100644
index 0000000..a485a9b
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/basic.swift
@@ -0,0 +1,48 @@
+class Foo {
+  /// This is just some documentation
+  func methodWithoutParameters() {
+  }
+
+  func methodWithParameters(param1: Foo, param2: Foo) {
+  }
+
+  @discardableResult
+  private func privateMethodWithAnnotation() -> Foo? {
+    return nil
+  }
+
+  var anInstanceVariable: String?
+
+  func justAnotherMethod() {
+  }
+}
+
+class OtherClass {
+  func foo() {
+  }
+
+  var computedVariable: Int {
+    return 0
+  }
+}
+
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=2:1 -end-pos=5:1 > %t.result/L2-5.swift
+// RUN: diff -u %S/Outputs/L2-5.swift.expected %t.result/L2-5.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=5:1 > %t.result/L3-5.swift
+// RUN: diff -u %S/Outputs/L3-5.swift.expected %t.result/L3-5.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=6:1 -end-pos=8:1 > %t.result/L6-8.swift
+// RUN: diff -u %S/Outputs/L6-8.swift.expected %t.result/L6-8.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=13:1 > %t.result/L3-13.swift
+// RUN: diff -u %S/Outputs/L3-13.swift.expected %t.result/L3-13.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=24:1 -end-pos=27:1 > %t.result/L24-27.swift
+// RUN: diff -u %S/Outputs/L24-27.swift.expected %t.result/L24-27.swift
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=4:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=4:1 -end-pos=8:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=1:1 -end-pos=14:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=14:1 -end-pos=15:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=15:1 -end-pos=23:1
diff --git a/test/stdlib/AppKit_Swift3.swift b/test/stdlib/AppKit_Swift3.swift
index 30432c2..07dbebc 100644
--- a/test/stdlib/AppKit_Swift3.swift
+++ b/test/stdlib/AppKit_Swift3.swift
@@ -17,4 +17,36 @@
   expectEqual(eventMask, .keyDown)
 }
 
+AppKitTests.test("NSLayoutPriority") {
+	let highPriority: NSLayoutPriority = NSLayoutPriorityDefaultHigh
+
+  let adjustedPriority1 = highPriority + 1
+  let adjustedPriority1RawValue: Float = NSLayoutPriorityDefaultHigh + 1
+  expectEqual(adjustedPriority1, adjustedPriority1RawValue)
+
+  let adjustedPriority2 = highPriority - 5.0
+  let adjustedPriority2RawValue: Float = NSLayoutPriorityDefaultHigh - 5.0
+  expectEqual(adjustedPriority2, adjustedPriority2RawValue)
+
+  let adjustedPriority3 = 5.0 + highPriority
+  let adjustedPriority3RawValue: Float = 5.0 + NSLayoutPriorityDefaultHigh
+  expectEqual(adjustedPriority3, adjustedPriority3RawValue)
+
+	// Inferred typing from result type
+  let adjustedPriority4: NSLayoutPriority = NSLayoutPriorityDefaultHigh + 2.0
+  let adjustedPriority4RawValue: Float = NSLayoutPriorityDefaultHigh + 2.0
+  expectEqual(adjustedPriority4, adjustedPriority4RawValue)
+
+	// Comparable
+	expectTrue(adjustedPriority1 > adjustedPriority2)
+	expectTrue(adjustedPriority2 < adjustedPriority1)
+
+	// Compound assignment
+	var variablePriority: NSLayoutPriority = NSLayoutPriorityDefaultHigh
+	variablePriority += 1
+	variablePriority -= 5.0
+	let variablePriorityRawValue: Float = NSLayoutPriorityDefaultHigh + 1 - 5.0
+	expectEqual(variablePriority, variablePriorityRawValue)
+}
+
 runAllTests()
diff --git a/test/stdlib/AppKit_Swift4.swift b/test/stdlib/AppKit_Swift4.swift
index 78406fd..843396e 100644
--- a/test/stdlib/AppKit_Swift4.swift
+++ b/test/stdlib/AppKit_Swift4.swift
@@ -105,4 +105,36 @@
   }
 }
 
+AppKitTests.test("NSLayoutPriority") {
+  let highPriority: NSLayoutConstraint.Priority = .defaultHigh
+
+  let adjustedPriority1 = highPriority + 1
+  let adjustedPriority1RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 1
+  expectEqual(adjustedPriority1.rawValue, adjustedPriority1RawValue)
+
+  let adjustedPriority2 = highPriority - 5.0
+  let adjustedPriority2RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue - 5.0
+  expectEqual(adjustedPriority2.rawValue, adjustedPriority2RawValue)
+
+  let adjustedPriority3 = 5.0 + highPriority
+  let adjustedPriority3RawValue: Float = 5.0 + NSLayoutConstraint.Priority.defaultHigh.rawValue
+  expectEqual(adjustedPriority3.rawValue, adjustedPriority3RawValue)
+
+  // Inferred typing from result type
+  let adjustedPriority4: NSLayoutConstraint.Priority = .defaultHigh + 2.0
+  let adjustedPriority4RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 2.0
+  expectEqual(adjustedPriority4.rawValue, adjustedPriority4RawValue)
+
+  // Comparable
+  expectTrue(adjustedPriority1 > adjustedPriority2)
+  expectTrue(adjustedPriority2 < adjustedPriority1)
+
+  // Compound assignment
+  var variablePriority: NSLayoutConstraint.Priority = .defaultHigh
+  variablePriority += 1
+  variablePriority -= 5.0
+  let variablePriorityRawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 1 - 5.0
+  expectEqual(variablePriority.rawValue, variablePriorityRawValue)
+}
+
 runAllTests()
diff --git a/test/stdlib/ArrayDiagnostics.swift b/test/stdlib/ArrayDiagnostics.swift
index d1f6f6b..144a107 100644
--- a/test/stdlib/ArrayDiagnostics.swift
+++ b/test/stdlib/ArrayDiagnostics.swift
@@ -5,7 +5,8 @@
 func test_ArrayOfNotEquatableIsNotEquatable() {
   var a = [ NotEquatable(), NotEquatable() ]
   // FIXME: This is an awful error.
-  if a == a {} // expected-error {{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+  if a == a {} // expected-error {{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+  // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
 }
 
diff --git a/test/stdlib/Intents.swift b/test/stdlib/Intents.swift
index de7a3fd..d0b19bf 100644
--- a/test/stdlib/Intents.swift
+++ b/test/stdlib/Intents.swift
@@ -75,4 +75,32 @@
 }
 #endif
 
+#if os(iOS)
+if #available(iOS 11.0, *) {
+  IntentsTestSuite.test("INSetProfileInCarIntent Initializers/\(swiftVersion)") {
+#if swift(>=4)
+    _ = INSetProfileInCarIntent()
+    _ = INSetProfileInCarIntent(isDefaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileName: nil)
+    _ = INSetProfileInCarIntent(profileName: nil, isDefaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil, isDefaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+    _ = INSetProfileInCarIntent(
+      profileNumber: nil, profileName: nil, isDefaultProfile: nil)
+#else
+    _ = INSetProfileInCarIntent()
+    _ = INSetProfileInCarIntent(defaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileName: nil)
+    _ = INSetProfileInCarIntent(profileName: nil, defaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil, defaultProfile: nil)
+    _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+    _ = INSetProfileInCarIntent(
+      profileNumber: nil, profileName: nil, defaultProfile: nil)
+#endif
+  }
+}
+#endif
+
 runAllTests()
diff --git a/test/stdlib/KeyPathImplementation.swift b/test/stdlib/KeyPathImplementation.swift
index 8ccde01..8151dc1 100644
--- a/test/stdlib/KeyPathImplementation.swift
+++ b/test/stdlib/KeyPathImplementation.swift
@@ -12,8 +12,7 @@
   return (offset + alignMask) & ~alignMask
 }
 
-// FIXME: Object header size will eventually be MemoryLayout<Int>.size * 2
-let classHeaderSize = MemoryLayout<Int>.size + 8
+let classHeaderSize = MemoryLayout<Int>.size * 2
 
 class C<T> {
   var x: Int
diff --git a/test/stdlib/StringDiagnostics.swift b/test/stdlib/StringDiagnostics.swift
index 2712ee3..1d36b11 100644
--- a/test/stdlib/StringDiagnostics.swift
+++ b/test/stdlib/StringDiagnostics.swift
@@ -53,6 +53,9 @@
   let a10 = nsString <= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
   let a11 = nsString >= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
   let a12 = nsString > s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
+  
+  // Shouldn't suggest 'as' in a pattern-matching context, as opposed to all these other situations
+  if case nsString = "" {} // expected-error{{expression pattern of type 'NSString' cannot match values of type 'String'}}
 }
 
 func testStringDeprecation(hello: String) {
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 70792c1..6910166 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -3677,6 +3677,50 @@
         let h3 = d3.hashValue
         expectEqual(h1, h3)
     }
+    
+    func test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+        var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<6]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        expectEqual(data, Data(bytes: [4, 0xFF]))
+    }
+    
+    func test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+        var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<6]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+        var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+        base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+        var data = base[4..<6]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+        var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<6]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
+    
+    func test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+        var base = Data(referencing: AllOnesData(length: 1))
+        base.count = 10
+        var data = base[4..<6]
+        data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+            ptr.advanced(by: 1).pointee = 0xFF
+        }
+        expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+    }
 }
 
 #if !FOUNDATION_XCTEST
@@ -3988,6 +4032,11 @@
 DataTests.test("test_slice_resize_growth") { TestData().test_slice_resize_growth() }
 DataTests.test("test_sliceEnumeration") { TestData().test_sliceEnumeration() }
 DataTests.test("test_hashEmptyData") { TestData().test_hashEmptyData() }
+DataTests.test("test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
 
 // XCTest does not have a crash detection, whereas lit does
 DataTests.test("bounding failure subdata") {
diff --git a/test/stdlib/TestJSONEncoder.swift b/test/stdlib/TestJSONEncoder.swift
index 5ed50b8..b0bf177 100644
--- a/test/stdlib/TestJSONEncoder.swift
+++ b/test/stdlib/TestJSONEncoder.swift
@@ -478,6 +478,22 @@
     _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
   }
 
+  func testDecodingConcreteTypeParameter() {
+      let encoder = JSONEncoder()
+      guard let json = try? encoder.encode(Employee.testValue) else {
+          expectUnreachable("Unable to encode Employee.")
+          return
+      }
+
+      let decoder = JSONDecoder()
+      guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: json) else {
+          expectUnreachable("Failed to decode Employee as Person from JSON.")
+          return
+      }
+
+      expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+  }
+
   // MARK: - Helper Functions
   private var _jsonEmptyDictionary: Data {
     return "{}".data(using: .utf8)!
@@ -1104,5 +1120,6 @@
 JSONEncoderTests.test("testInterceptDecimal") { TestJSONEncoder().testInterceptDecimal() }
 JSONEncoderTests.test("testInterceptURL") { TestJSONEncoder().testInterceptURL() }
 JSONEncoderTests.test("testTypeCoercion") { TestJSONEncoder().testTypeCoercion() }
+JSONEncoderTests.test("testDecodingConcreteTypeParameter") { TestJSONEncoder().testDecodingConcreteTypeParameter() }
 runAllTests()
 #endif
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index f5c4685..489261a 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -522,7 +522,7 @@
             let float = (number!) as? Float
             let expectedFloat = Float(uint32!)
             // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+            if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
                 testFloat(expectedFloat, float)
             }
             
@@ -658,16 +658,16 @@
             let uint = (number!) as? UInt
             expectEqual(UInt(exactly: interestingValue), uint)
 
-            // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
-                let float = (number!) as? Float
-                let expectedFloat = Float(uint!)
-                testFloat(expectedFloat, float)
+            let float = (number!) as? Float
+            let expectedFloat = Float(exactly: uint!)
+            if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+              expectNil(expectedFloat)
+            } else {
+              testFloat(expectedFloat, float)
             }
-            
-            
+          
             let double = (number!) as? Double
-            let expectedDouble = Double(uint!)
+            let expectedDouble = Double(exactly: uint!)
             testDouble(expectedDouble, double)
         }
         let bridged = interestingValue as NSNumber
diff --git a/test/stdlib/TestPlistEncoder.swift b/test/stdlib/TestPlistEncoder.swift
index d7b037b..d38ef76 100644
--- a/test/stdlib/TestPlistEncoder.swift
+++ b/test/stdlib/TestPlistEncoder.swift
@@ -198,6 +198,22 @@
     _testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
   }
 
+  func testDecodingConcreteTypeParameter() {
+      let encoder = PropertyListEncoder()
+      guard let plist = try? encoder.encode(Employee.testValue) else {
+          expectUnreachable("Unable to encode Employee.")
+          return
+      }
+
+      let decoder = PropertyListDecoder()
+      guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: plist) else {
+          expectUnreachable("Failed to decode Employee as Person from plist.")
+          return
+      }
+
+      expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+  }
+
   // MARK: - Helper Functions
   private var _plistEmptyDictionaryBinary: Data {
     return Data(base64Encoded: "YnBsaXN0MDDQCAAAAAAAAAEBAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJ")!
@@ -731,5 +747,6 @@
 PropertyListEncoderTests.test("testInterceptData") { TestPropertyListEncoder().testInterceptData() }
 PropertyListEncoderTests.test("testInterceptDate") { TestPropertyListEncoder().testInterceptDate() }
 PropertyListEncoderTests.test("testTypeCoercion") { TestPropertyListEncoder().testTypeCoercion() }
+PropertyListEncoderTests.test("testDecodingConcreteTypeParameter") { TestPropertyListEncoder().testDecodingConcreteTypeParameter() }
 runAllTests()
 #endif
diff --git a/test/stdlib/UIKit.swift b/test/stdlib/UIKit.swift
index 800668d..a5703ff 100644
--- a/test/stdlib/UIKit.swift
+++ b/test/stdlib/UIKit.swift
@@ -1,13 +1,21 @@
-// RUN: %target-run-simple-swift
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-build-swift -swift-version 3 %s -o %t/a.out3 && %target-run %t/a.out3
+// RUN: %target-build-swift -swift-version 4 %s -o %t/a.out4 && %target-run %t/a.out4
 // REQUIRES: executable_test
-// REQUIRES: OS=ios
+// UNSUPPORTED: OS=macosx
+// REQUIRES: objc_interop
 
 import UIKit
 import StdlibUnittest
 import StdlibUnittestFoundationExtras
 
-let UIKitTests = TestSuite("UIKit")
+#if swift(>=4)
+  let UIKitTests = TestSuite("UIKit_Swift4")
+#else
+  let UIKitTests = TestSuite("UIKit_Swift3")
+#endif
 
+#if !os(watchOS) && !os(tvOS)
 private func printDevice(_ o: UIDeviceOrientation) -> String {
   var s = "\(o.isPortrait) \(UIDeviceOrientationIsPortrait(o)), "
   s += "\(o.isLandscape) \(UIDeviceOrientationIsLandscape(o)), "
@@ -60,6 +68,7 @@
   expectEqual("false false, true true",
     printInterface(.landscapeRight))
 }
+#endif
 
 UIKitTests.test("UIEdgeInsets") {
   let insets = [
@@ -79,6 +88,66 @@
   checkEquatable(offsets, oracle: { $0 == $1 })
 }
 
+UIKitTests.test("UIFont.Weight") {
+  guard #available(iOS 8.2, *) else { return }
+  #if swift(>=4) // Swift 4
+    let regularFontWeight: UIFont.Weight = .regular
+
+    expectTrue(regularFontWeight == .regular)
+    expectTrue(regularFontWeight > .light)
+    expectTrue(regularFontWeight < .heavy)
+    expectTrue(regularFontWeight + 0.1 == 0.1 + regularFontWeight)
+  #else // Swift 3
+    let regularFontWeight: UIFontWeight = UIFontWeightRegular
+
+    expectTrue(regularFontWeight == UIFontWeightRegular)
+    expectTrue(regularFontWeight > UIFontWeightLight)
+    expectTrue(regularFontWeight < UIFontWeightHeavy)
+    expectTrue(regularFontWeight + 0.1 == 0.1 + UIFontWeightRegular)
+  #endif
+}
+
+#if !os(watchOS)
+UIKitTests.test("UILayoutPriority") {
+  #if swift(>=4) // Swift 4
+    let lowLayoutPriority: UILayoutPriority = .defaultLow
+    let highLayoutPriority: UILayoutPriority = .defaultHigh
+
+    expectTrue(lowLayoutPriority < highLayoutPriority)
+
+    expectTrue(lowLayoutPriority + 2.0 == UILayoutPriority(lowLayoutPriority.rawValue + 2.0))
+    expectTrue(2.0 + lowLayoutPriority == UILayoutPriority(lowLayoutPriority.rawValue + 2.0))
+    expectTrue(lowLayoutPriority - 2.0 == UILayoutPriority(lowLayoutPriority.rawValue - 2.0))
+    expectTrue(highLayoutPriority - lowLayoutPriority == highLayoutPriority.rawValue - lowLayoutPriority.rawValue)
+
+    expectTrue(lowLayoutPriority + (highLayoutPriority - lowLayoutPriority) == highLayoutPriority)
+
+    var mutablePriority = lowLayoutPriority
+    mutablePriority -= 1.0
+    mutablePriority += 2.0
+    expectTrue(mutablePriority == lowLayoutPriority + 1.0)
+
+    let priorotyRange = lowLayoutPriority...highLayoutPriority
+    expectTrue(priorotyRange.contains(.defaultLow))
+    expectFalse(priorotyRange.contains(.required))
+  #else // Swift 3
+    let lowLayoutPriority: UILayoutPriority = UILayoutPriorityDefaultLow
+    let highLayoutPriority: UILayoutPriority = UILayoutPriorityDefaultHigh
+
+    expectTrue(lowLayoutPriority < highLayoutPriority)
+
+    expectTrue(2.0 + lowLayoutPriority == lowLayoutPriority + 2.0)
+    expectTrue(lowLayoutPriority + (highLayoutPriority - lowLayoutPriority) == highLayoutPriority)
+
+    var mutablePriority = lowLayoutPriority
+    mutablePriority -= 1.0
+    mutablePriority += 2.0
+    expectTrue(mutablePriority == lowLayoutPriority + 1.0)
+  #endif
+}
+#endif
+
+#if !os(watchOS)
 class TestChildView : UIView, CustomPlaygroundQuickLookable {
   convenience init() {
     self.init(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
@@ -95,6 +164,7 @@
     "TestChildView custom quicklookable should have been invoked")
   }
 }
+#endif
 
 UIKitTests.test("NSValue bridging") {
   expectBridgeToNSValue(UIEdgeInsets(top: 17, left: 38, bottom: 6, right: 79),
diff --git a/test/stdlib/UnsafeRawBufferPointer.swift b/test/stdlib/UnsafeRawBufferPointer.swift
index a5f5897..442f6fc 100644
--- a/test/stdlib/UnsafeRawBufferPointer.swift
+++ b/test/stdlib/UnsafeRawBufferPointer.swift
@@ -100,7 +100,10 @@
   let buffer = UnsafeMutableRawBufferPointer.allocate(count: 30)
   defer { buffer.deallocate() }
   let source = stride(from: 5 as Int64, to: 0, by: -1)
-  var (it,bound) = buffer.initializeMemory(as: Int64.self, from: source)
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
+  var (it, bound) = buffer.initializeMemory(as: Int64.self, from: source)
   let idx = bound.endIndex * MemoryLayout<Int64>.stride
   expectEqual(it.next()!, 2)
   expectEqual(idx, 24)
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
index 2efa730..7b487bc 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
@@ -283,6 +283,8 @@
 KIND(RangeSingleExpression, "source.lang.swift.range.singleexpression")
 KIND(RangeSingleDeclaration, "source.lang.swift.range.singledeclaration")
 KIND(RangeMultiStatement, "source.lang.swift.range.multistatement")
+KIND(RangeMultiTypeMemberDeclaration,
+     "source.lang.swift.range.multitypememberdeclaration")
 KIND(RangeInvalid, "source.lang.swift.range.invalid")
 KIND(NameObjc, "source.lang.name.kind.objc")
 KIND(NameSwift, "source.lang.name.kind.swift")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 22f3457..7848c72 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -377,6 +377,8 @@
       continue;
     if (Arg == "-c")
       continue;
+    if (Arg == "-v")
+      continue;
     if (Arg == "-Xfrontend")
       continue;
     if (Arg == "-embed-bitcode")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 4ffea4c..9be32b6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -21,11 +21,11 @@
 #include "swift/AST/ASTPrinter.h"
 #include "swift/AST/ASTWalker.h"
 #include "swift/AST/GenericSignature.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/Frontend/Frontend.h"
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/IDE/CommentConversion.h"
 #include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/IDE/SyntaxModel.h"
 #include "swift/IDE/Refactoring.h"
 // This is included only for createLazyResolver(). Move to different header ?
@@ -346,7 +346,7 @@
 
   if (DefaultImplementationOf) {
     llvm::raw_svector_ostream OS(Info.ProvideImplementationOfUSR);
-    SwiftLangSupport::printUSR((ValueDecl*)DefaultImplementationOf, OS);
+    SwiftLangSupport::printUSR((const ValueDecl*)DefaultImplementationOf, OS);
   }
 
   Info.IsUnavailable = AvailableAttr::isUnavailable(D);
@@ -369,13 +369,13 @@
         assert(DocRef.find(Open) != StringRef::npos);
         auto FirstPart = DocRef.substr(0, DocRef.find(Open) + (Open).size());
         auto SecondPart = DocRef.substr(FirstPart.size());
-        auto ExtendedName = ((ExtensionDecl*)D)->getExtendedType()->
+        auto ExtendedName = ((const ExtensionDecl*)D)->getExtendedType()->
           getAnyNominal()->getName().str();
         assert(SecondPart.startswith(ExtendedName));
         SecondPart = SecondPart.substr(ExtendedName.size());
         llvm::SmallString<128> UpdatedDocBuffer;
         UpdatedDocBuffer.append(FirstPart);
-        UpdatedDocBuffer.append(((NominalTypeDecl*)SynthesizedTarget)->getName().
+        UpdatedDocBuffer.append(((const NominalTypeDecl*)SynthesizedTarget)->getName().
                                 str());
         UpdatedDocBuffer.append(SecondPart);
         OS << UpdatedDocBuffer;
@@ -522,7 +522,7 @@
     return;
   if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
     if (SynthesizedTarget) {
-      passExtends((ValueDecl*)SynthesizedTarget, Consumer);
+      passExtends((const ValueDecl*)SynthesizedTarget, Consumer);
     } else if (Type T = ED->getExtendedType()) {
       if (auto TD = getTypeDeclFromType(T))
         passExtends(TD, Consumer);
@@ -1041,10 +1041,11 @@
   }
 
   bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+                               Optional<AccessKind> AccKind,
                                bool IsOpenBracket) override {
     // Treat both open and close brackets equally
     return visitDeclReference(D, Range, nullptr, nullptr, Type(),
-                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
   }
 
   bool isLocal(Decl *D) const {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 397f25b..4471725 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -23,7 +23,6 @@
 #include "swift/AST/ASTPrinter.h"
 #include "swift/AST/ASTVisitor.h"
 #include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/AST/DiagnosticsClangImporter.h"
 #include "swift/AST/DiagnosticsParse.h"
 #include "swift/Basic/SourceManager.h"
@@ -33,6 +32,7 @@
 #include "swift/IDE/CodeCompletion.h"
 #include "swift/IDE/CommentConversion.h"
 #include "swift/IDE/Formatting.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/IDE/SyntaxModel.h"
 #include "swift/Subsystems.h"
 
@@ -876,10 +876,11 @@
   }
 
   bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+                               Optional<AccessKind> AccKind,
                                bool IsOpenBracket) override {
     // We should treat both open and close brackets equally
     return visitDeclReference(D, Range, nullptr, nullptr, Type(),
-                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
   }
 
   void annotate(const Decl *D, bool IsRef, CharSourceRange Range) {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 8c4a44a..563177b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -451,6 +451,8 @@
     case swift::ide::RangeKind::SingleStatement: return KindRangeSingleStatement;
     case swift::ide::RangeKind::SingleDecl: return KindRangeSingleDeclaration;
     case swift::ide::RangeKind::MultiStatement: return KindRangeMultiStatement;
+    case swift::ide::RangeKind::MultiTypeMemberDecl:
+      return KindRangeMultiTypeMemberDeclaration;
     case swift::ide::RangeKind::PartOfExpression: return KindRangeInvalid;
     case swift::ide::RangeKind::Invalid: return KindRangeInvalid;
   }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 7993900..a96492b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -19,13 +19,13 @@
 #include "swift/AST/ASTPrinter.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/NameLookup.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/AST/SwiftNameTranslation.h"
 #include "swift/Basic/SourceManager.h"
 #include "swift/Frontend/Frontend.h"
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/IDE/CommentConversion.h"
 #include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/IDE/Utils.h"
 #include "swift/IDE/Refactoring.h"
 #include "swift/Markup/XMLUtils.h"
@@ -1515,6 +1515,7 @@
         return;
       }
       case RangeKind::SingleDecl:
+      case RangeKind::MultiTypeMemberDecl:
       case RangeKind::MultiStatement:
       case RangeKind::SingleStatement: {
         Receiver(Result);
diff --git a/tools/SwiftSyntax/SwiftSyntax.swift b/tools/SwiftSyntax/SwiftSyntax.swift
index 343f705..c3a3244 100644
--- a/tools/SwiftSyntax/SwiftSyntax.swift
+++ b/tools/SwiftSyntax/SwiftSyntax.swift
@@ -37,12 +37,10 @@
       throw ParserError.swiftcFailed(result.exitCode, result.stderr)
     }
     let decoder = JSONDecoder()
-    let raw = try decoder.decode([RawSyntax].self, from: result.stdoutData)
-    let topLevelNodes = raw.map { Syntax.fromRaw($0) }
-    let eof = topLevelNodes.last! as! TokenSyntax
-    let decls = Array(topLevelNodes.dropLast()) as! [DeclSyntax]
-    let declList = SyntaxFactory.makeDeclList(decls)
-    return SyntaxFactory.makeSourceFile(topLevelDecls: declList,
-                                        eofToken: eof)
+    let raw = try decoder.decode(RawSyntax.self, from: result.stdoutData)
+    guard let file = Syntax.fromRaw(raw) as? SourceFileSyntax else {
+      throw ParserError.invalidFile
+    }
+    return file
   }
 }
diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp
index 701113a..0a812af 100644
--- a/tools/sil-func-extractor/SILFunctionExtractor.cpp
+++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp
@@ -254,34 +254,15 @@
   Invocation.getLangOptions().EnableAccessControl = false;
   Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
 
-  // Load the input file.
+  serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+                                      extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
   }
 
-  // If it looks like we have an AST, set the source file kind to SIL and the
-  // name of the module to the file's name.
-  Invocation.addInputBuffer(FileBufOrErr.get().get());
-
-  serialization::ExtendedValidationInfo extendedInfo;
-  auto result = serialization::validateSerializedAST(
-      FileBufOrErr.get()->getBuffer(), &extendedInfo);
-  bool HasSerializedAST = result.status == serialization::Status::Valid;
-
-  if (HasSerializedAST) {
-    const StringRef Stem = ModuleName.size()
-                               ? StringRef(ModuleName)
-                               : llvm::sys::path::stem(InputFilename);
-    Invocation.setModuleName(Stem);
-    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
-  } else {
-    Invocation.setModuleName("main");
-    Invocation.setInputKind(InputFileKind::IFK_SIL);
-  }
-
   SILOptions &SILOpts = Invocation.getSILOptions();
   SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
       AssumeUnqualifiedOwnershipWhenParsing;
@@ -300,7 +281,7 @@
 
   // Load the SIL if we have a module. We have to do this after SILParse
   // creating the unfortunate double if statement.
-  if (HasSerializedAST) {
+  if (Invocation.hasSerializedAST()) {
     assert(!CI.hasSILModule() &&
            "performSema() should not create a SILModule.");
     CI.setSILModule(
diff --git a/tools/sil-llvm-gen/SILLLVMGen.cpp b/tools/sil-llvm-gen/SILLLVMGen.cpp
index c04f619..5498216 100644
--- a/tools/sil-llvm-gen/SILLLVMGen.cpp
+++ b/tools/sil-llvm-gen/SILLLVMGen.cpp
@@ -167,35 +167,15 @@
   Opts.OutputFilenames.push_back(OutputFilename);
   Opts.OutputKind = OutputKind;
 
-  // Load the input file.
+  serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+                                      extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
   }
 
-  // If it looks like we have an AST, set the source file kind to SIL and the
-  // name of the module to the file's name.
-  Invocation.addInputBuffer(FileBufOrErr.get().get());
-
-  serialization::ExtendedValidationInfo extendedInfo;
-  auto result = serialization::validateSerializedAST(
-      FileBufOrErr.get()->getBuffer(), &extendedInfo);
-  bool HasSerializedAST = result.status == serialization::Status::Valid;
-
-  if (HasSerializedAST) {
-    const StringRef Stem = ModuleName.size()
-                               ? StringRef(ModuleName)
-                               : llvm::sys::path::stem(InputFilename);
-    Invocation.setModuleName(Stem);
-    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
-  } else {
-    const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
-    Invocation.setModuleName(Name);
-    Invocation.setInputKind(InputFileKind::IFK_SIL);
-  }
-
   CompilerInstance CI;
   PrintingDiagnosticConsumer PrintDiags;
   CI.addDiagnosticConsumer(&PrintDiags);
@@ -216,7 +196,7 @@
 
   // Load the SIL if we have a module. We have to do this after SILParse
   // creating the unfortunate double if statement.
-  if (HasSerializedAST) {
+  if (Invocation.hasSerializedAST()) {
     assert(!CI.hasSILModule() &&
            "performSema() should not create a SILModule.");
     CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/sil-nm/SILNM.cpp b/tools/sil-nm/SILNM.cpp
index ec5df3c..b3eddc9 100644
--- a/tools/sil-nm/SILNM.cpp
+++ b/tools/sil-nm/SILNM.cpp
@@ -168,34 +168,15 @@
   Invocation.getLangOptions().EnableAccessControl = false;
   Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
 
-  // Load the input file.
+  serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+                                      extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
   }
 
-  // If it looks like we have an AST, set the source file kind to SIL and the
-  // name of the module to the file's name.
-  Invocation.addInputBuffer(FileBufOrErr.get().get());
-
-  serialization::ExtendedValidationInfo extendedInfo;
-  auto result = serialization::validateSerializedAST(
-      FileBufOrErr.get()->getBuffer(), &extendedInfo);
-  bool HasSerializedAST = result.status == serialization::Status::Valid;
-
-  if (HasSerializedAST) {
-    const StringRef Stem = ModuleName.size()
-                               ? StringRef(ModuleName)
-                               : llvm::sys::path::stem(InputFilename);
-    Invocation.setModuleName(Stem);
-    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
-  } else {
-    Invocation.setModuleName("main");
-    Invocation.setInputKind(InputFileKind::IFK_SIL);
-  }
-
   SILOptions &SILOpts = Invocation.getSILOptions();
   SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
       AssumeUnqualifiedOwnershipWhenParsing;
@@ -214,7 +195,7 @@
 
   // Load the SIL if we have a module. We have to do this after SILParse
   // creating the unfortunate double if statement.
-  if (HasSerializedAST) {
+  if (Invocation.hasSerializedAST()) {
     assert(!CI.hasSILModule() &&
            "performSema() should not create a SILModule.");
     CI.setSILModule(
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index d7d5e66..b222dcd 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -311,7 +311,7 @@
   SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
   SILOpts.AssertConfig = AssertConfId;
   if (OptimizationGroup != OptGroup::Diagnostics)
-    SILOpts.Optimization = SILOptions::SILOptMode::Optimize;
+    SILOpts.OptMode = OptimizationMode::ForSpeed;
   SILOpts.EnableSILOwnership = EnableSILOwnershipOpt;
   SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
     AssumeUnqualifiedOwnershipWhenParsing;
@@ -342,35 +342,15 @@
     }
   }
 
-  // Load the input file.
+  serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-    llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+                                      extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
   }
 
-  // If it looks like we have an AST, set the source file kind to SIL and the
-  // name of the module to the file's name.
-  Invocation.addInputBuffer(FileBufOrErr.get().get());
-
-  serialization::ExtendedValidationInfo extendedInfo;
-  auto result = serialization::validateSerializedAST(
-      FileBufOrErr.get()->getBuffer(), &extendedInfo);
-  bool HasSerializedAST = result.status == serialization::Status::Valid;
-
-  if (HasSerializedAST) {
-    const StringRef Stem = ModuleName.size() ?
-                             StringRef(ModuleName) :
-                             llvm::sys::path::stem(InputFilename);
-    Invocation.setModuleName(Stem);
-    Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
-  } else {
-    const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
-    Invocation.setModuleName(Name);
-    Invocation.setInputKind(InputFileKind::IFK_SIL);
-  }
-
   CompilerInstance CI;
   PrintingDiagnosticConsumer PrintDiags;
   CI.addDiagnosticConsumer(&PrintDiags);
@@ -391,7 +371,7 @@
 
   // Load the SIL if we have a module. We have to do this after SILParse
   // creating the unfortunate double if statement.
-  if (HasSerializedAST) {
+  if (Invocation.hasSerializedAST()) {
     assert(!CI.hasSILModule() &&
            "performSema() should not create a SILModule.");
     CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 5cf9e47..943ae43 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -1282,6 +1282,9 @@
       return true;
     if (VD->getBaseName().empty())
       return true;
+    // This shouldn't happen, being forgiving here.
+    if (!VD->hasAccess())
+      return true;
     switch (VD->getFormalAccess()) {
     case AccessLevel::Internal:
     case AccessLevel::Private:
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index abb6af8..2b18f5c 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -22,7 +22,6 @@
 #include "swift/AST/ASTMangler.h"
 #include "swift/AST/PrintOptions.h"
 #include "swift/AST/RawComment.h"
-#include "swift/AST/SourceEntityWalker.h"
 #include "swift/AST/USRGeneration.h"
 #include "swift/Demangling/Demangle.h"
 #include "swift/Basic/LangOptions.h"
@@ -35,6 +34,7 @@
 #include "swift/IDE/CommentConversion.h"
 #include "swift/IDE/ModuleInterfacePrinting.h"
 #include "swift/IDE/REPLCodeCompletion.h"
+#include "swift/IDE/SourceEntityWalker.h"
 #include "swift/IDE/SyntaxModel.h"
 #include "swift/IDE/Utils.h"
 #include "swift/Index/Index.h"
@@ -1264,9 +1264,10 @@
   }
 
   bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+                               Optional<AccessKind> AccKind,
                                bool IsOpenBracket) override {
     return visitDeclReference(D, Range, nullptr, nullptr, Type(),
-                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
   }
 
   bool visitCallArgName(Identifier Name, CharSourceRange Range,
diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp
index d3d9f05..cba627f 100644
--- a/tools/swift-llvm-opt/LLVMOpt.cpp
+++ b/tools/swift-llvm-opt/LLVMOpt.cpp
@@ -302,7 +302,7 @@
 
   if (Optimized) {
     IRGenOptions Opts;
-    Opts.Optimize = true;
+    Opts.OptMode = OptimizationMode::ForSpeed;
 
     // Then perform the optimizations.
     performLLVMOptimizations(Opts, M.get(), TM.get());
diff --git a/tools/swift-refactor/swift-refactor.cpp b/tools/swift-refactor/swift-refactor.cpp
index 10613bb..fc048f6 100644
--- a/tools/swift-refactor/swift-refactor.cpp
+++ b/tools/swift-refactor/swift-refactor.cpp
@@ -50,6 +50,8 @@
                       "strings-concatenation-to-interpolation", "Perform strings concatenation to interpolation refactoring"),
            clEnumValN(RefactoringKind::ExtractFunction,
                       "extract-function", "Perform extract function refactoring"),
+           clEnumValN(RefactoringKind::MoveMembersToExtension,
+                      "move-to-extension", "Move selected members to an extension"),
            clEnumValN(RefactoringKind::GlobalRename,
                       "syntactic-rename", "Perform syntactic rename"),
            clEnumValN(RefactoringKind::FindGlobalRenameRanges,
diff --git a/unittests/Reflection/TypeRef.cpp b/unittests/Reflection/TypeRef.cpp
index 29d943f..c736ce5 100644
--- a/unittests/Reflection/TypeRef.cpp
+++ b/unittests/Reflection/TypeRef.cpp
@@ -147,7 +147,7 @@
   EXPECT_NE(F4, F1);
 
   // Test parameter with and without inout/shared/variadic and/or label.
-  ParameterTypeFlags paramFlags;
+  ParameterFlags paramFlags;
   auto inoutFlags = paramFlags.withInOut(true);
   auto variadicFlags = paramFlags.withVariadic(true);
   auto sharedFlags = paramFlags.withShared(true);
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index 32c4c20..f9b897e 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -938,17 +938,27 @@
 // Tests for resilient witness table instantiation, with runtime-provided
 // default requirements
 
+struct WitnessTableSlice {
+  WitnessTable **tables;
+  size_t count;
+};
+
 static void witnessTableInstantiator(WitnessTable *instantiatedTable,
                                      const Metadata *type,
                                      void * const *instantiationArgs) {
   EXPECT_EQ(type, nullptr);
-  EXPECT_EQ(instantiationArgs, nullptr);
 
   EXPECT_EQ(((void **) instantiatedTable)[0], (void*) 123);
   EXPECT_EQ(((void **) instantiatedTable)[1], (void*) 234);
 
   // The last witness is computed dynamically at instantiation time.
   ((void **) instantiatedTable)[2] = (void *) 345;
+
+  auto conditionalTables = (WitnessTableSlice *)instantiationArgs;
+
+  EXPECT_EQ(conditionalTables->count, 1UL);
+  EXPECT_EQ(conditionalTables->tables[0], (void *)678);
+  ((void **)instantiatedTable)[-1] = conditionalTables->tables[0];
 }
 
 static void fakeDefaultWitness1() {}
@@ -1013,6 +1023,9 @@
   (void *) 567
 };
 
+WitnessTable *conditionalTablesBuffer[] = {(WitnessTable *)678};
+WitnessTableSlice conditionalTablesSlice = {conditionalTablesBuffer, 1};
+
 TEST(WitnessTableTest, getGenericWitnessTable) {
   EXPECT_EQ(sizeof(GenericWitnessTableStorage), sizeof(GenericWitnessTable));
 
@@ -1048,7 +1061,7 @@
   // and an initializer, so we must instantiate.
   {
     tableStorage2.WitnessTableSizeInWords = 5;
-    tableStorage2.WitnessTablePrivateSizeInWords = 1;
+    tableStorage2.WitnessTablePrivateSizeInWords = 1 + 1;
     initializeRelativePointer(&tableStorage2.Protocol, &testProtocol.descriptor);
     initializeRelativePointer(&tableStorage2.Pattern, witnesses);
     initializeRelativePointer(&tableStorage2.Instantiator,
@@ -1060,12 +1073,13 @@
 
     RaceTest_ExpectEqual<const WitnessTable *>(
       [&]() -> const WitnessTable * {
-        const WitnessTable *instantiatedTable =
-            swift_getGenericWitnessTable(table, nullptr, nullptr);
+        const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+            table, nullptr, (void**)&conditionalTablesSlice);
 
         EXPECT_NE(instantiatedTable, table->Pattern.get());
 
-        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
 
         EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
         EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
@@ -1080,7 +1094,7 @@
   // Conformance needs one default requirement to be filled in
   {
     tableStorage3.WitnessTableSizeInWords = 4;
-    tableStorage3.WitnessTablePrivateSizeInWords = 1;
+    tableStorage3.WitnessTablePrivateSizeInWords = 1 + 1;
     initializeRelativePointer(&tableStorage3.Protocol, &testProtocol.descriptor);
     initializeRelativePointer(&tableStorage3.Pattern, witnesses);
     initializeRelativePointer(&tableStorage3.Instantiator, witnessTableInstantiator);
@@ -1091,12 +1105,13 @@
 
     RaceTest_ExpectEqual<const WitnessTable *>(
       [&]() -> const WitnessTable * {
-        const WitnessTable *instantiatedTable =
-            swift_getGenericWitnessTable(table, nullptr, nullptr);
+        const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+            table, nullptr, (void**)&conditionalTablesSlice);
 
         EXPECT_NE(instantiatedTable, table->Pattern.get());
 
-        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
 
         EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
         EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
@@ -1112,7 +1127,7 @@
   // to be filled in
   {
     tableStorage4.WitnessTableSizeInWords = 3;
-    tableStorage4.WitnessTablePrivateSizeInWords = 1;
+    tableStorage4.WitnessTablePrivateSizeInWords = 1 + 1;
     initializeRelativePointer(&tableStorage4.Protocol, &testProtocol.descriptor);
     initializeRelativePointer(&tableStorage4.Pattern, witnesses);
     initializeRelativePointer(&tableStorage4.Instantiator, witnessTableInstantiator);
@@ -1123,12 +1138,13 @@
 
     RaceTest_ExpectEqual<const WitnessTable *>(
       [&]() -> const WitnessTable * {
-        const WitnessTable *instantiatedTable =
-            swift_getGenericWitnessTable(table, nullptr, nullptr);
+        const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+            table, nullptr, (void**)&conditionalTablesSlice);
 
         EXPECT_NE(instantiatedTable, table->Pattern.get());
 
-        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+        EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
 
         EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
         EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
diff --git a/utils/build-script-impl b/utils/build-script-impl
index ff0bbb2..1bfbcc5 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2481,6 +2481,11 @@
                     continue
                 fi
 
+                # FIXME: Always re-build foundation on non-darwin platforms.
+                # Remove this when products build in the CMake system.
+                echo "Cleaning the Foundation build directory"
+                call rm -rf "${build_dir}"
+
                 with_pushd "${FOUNDATION_SOURCE_DIR}" \
                     call env SWIFTC="${SWIFTC_BIN}" CLANG="${LLVM_BIN}"/clang SWIFT="${SWIFT_BIN}" \
                       SDKROOT="${SWIFT_BUILD_PATH}" BUILD_DIR="${build_dir}" DSTROOT="$(get_host_install_destdir ${host})" PREFIX="$(get_host_install_prefix ${host})" ./configure "${FOUNDATION_BUILD_TYPE}" ${FOUNDATION_BUILD_ARGS[@]} -DXCTEST_BUILD_DIR=${XCTEST_BUILD_DIR} $LIBDISPATCH_BUILD_ARGS
@@ -2526,6 +2531,7 @@
                   else
                       echo "Skipping reconfiguration of libdispatch"
                   fi
+
                   with_pushd "${LIBDISPATCH_BUILD_DIR}" \
                       call make
                   with_pushd "${LIBDISPATCH_BUILD_DIR}/tests" \
@@ -2535,6 +2541,11 @@
                   continue
                 ;;
                 *)
+                  # FIXME: Always re-build libdispatch on non-darwin platforms.
+                  # Remove this when products build in the CMake system.
+                  echo "Cleaning the libdispatch build directory"
+                  call rm -rf "${LIBDISPATCH_BUILD_DIR}"
+
                   cmake_options=(
                     ${cmake_options[@]}
                     -DCMAKE_BUILD_TYPE:STRING="${LIBDISPATCH_BUILD_TYPE}"
diff --git a/utils/cmpcodesize/cmpcodesize/main.py b/utils/cmpcodesize/cmpcodesize/main.py
index 3f02353..224e556 100644
--- a/utils/cmpcodesize/cmpcodesize/main.py
+++ b/utils/cmpcodesize/cmpcodesize/main.py
@@ -24,7 +24,7 @@
 
 SHORTCUTS = {
     "O": "bin/Benchmark_O",
-    "Ounchecked": "bin/Benchmark_Ounchecked",
+    "Osize": "bin/Benchmark_Osize",
     "Onone": "bin/Benchmark_Onone",
     "dylib": "lib/swift/macosx/x86_64/libswiftCore.dylib",
 }
@@ -53,7 +53,7 @@
     Compares the files in the new and old build-dirs.
     Aliases:
         O          => bin/Benchmark_O
-        Ounchecked => bin/Benchmark_Ounchecked
+        Osize      => bin/Benchmark_Osize
         Onone      => bin/Benchmark_Onone
         dylib      => lib/swift/macosx/x86_64/libswiftCore.dylib
     Examples:
diff --git a/utils/dev-scripts/split-cmdline b/utils/dev-scripts/split-cmdline
index 364009e..736b1a2 100755
--- a/utils/dev-scripts/split-cmdline
+++ b/utils/dev-scripts/split-cmdline
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# splitcmdline - Split swift compiler command lines -------------*- python -*-
+# split-cmdline - Split swift compiler command lines ------------*- python -*-
 #
 # This source file is part of the Swift.org open source project
 #
@@ -14,7 +14,19 @@
 # Split swift compiler command lines into multiple lines.
 #
 # Reads the command line from stdin an outputs the split line to stdout.
+# Example:
 #
+# $ swiftc -c hello.swift -### | split-cmdline
+# /path-to-swift/bin/swift \
+#   -frontend \
+#   -c \
+#   -primary-file hello.swift \
+#   -target x86_64-apple-macosx10.9 \
+#   -enable-objc-interop \
+#   -color-diagnostics \
+#   -module-name hello \
+#   -o hello.o
+# 
 # Example usage in vim:
 # *) make sure that split-cmdline is in the $PATH
 # *) copy-paste the swift command line the text buffer
@@ -29,16 +41,15 @@
 import re
 import sys
 import os
-
+import shlex
 
 def main():
   for line in sys.stdin:
     first = True
     is_arg_param = False
     # Handle escaped spaces
-    args = re.sub('\\\\ ', '@#space#@', line).split()
+    args = shlex.split(line)
     for arg in args:
-      arg = re.sub('@#space#@', '\\ ', arg)
       if arg == '':
         continue
       if not first:
@@ -59,7 +70,10 @@
         first = True
         continue
 
-      print(arg, end='')
+      if ' ' in arg:
+        print('"' + arg + '"', end='')
+      else:
+        print(arg, end='')
 
       # A hard-coded list of options which expect a parameter
       is_arg_param = (arg in [
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index 07a9d5a..d6c57e1 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -19,6 +19,12 @@
     Node('FunctionCallArgumentList', kind='SyntaxCollection',
          element='FunctionCallArgument'),
 
+    Node('ArrayElementList', kind='SyntaxCollection',
+         element='ArrayElement'),
+
+    Node('DictionaryElementList', kind='SyntaxCollection',
+         element='DictionaryElement'),
+
     # The try operator.
     # try foo()
     # try? foo()
@@ -34,6 +40,24 @@
                    ]),
          ]),
 
+    # An identifier expression.
+    Node('IdentifierExpr', kind='Expr',
+         children=[
+             Child('Identifier', kind='IdentifierToken'),
+         ]),
+
+    # A nil expression.
+    Node('NilLiteralExpr', kind='Expr',
+         children=[
+             Child('NilKeyword', kind='NilToken'),
+         ]),
+
+    # A _ expression.
+    Node('DiscardAssignmentExpr', kind='Expr',
+         children=[
+             Child('Wildcard', kind='WildcardToken'),
+         ]),
+
     # A #line expression.
     Node('PoundLineExpr', kind='Expr',
          children=[
@@ -89,6 +113,22 @@
              Child('RightParen', kind='RightParenToken'),
          ]),
 
+    # Array literal, e.g. [1, 2, 3]
+    Node('ArrayExpr', kind='Expr',
+         children=[
+             Child('LeftSquare', kind='LeftSquareToken'),
+             Child('Elements', kind='ArrayElementList'),
+             Child('RightSquare', kind='RightSquareToken'),
+         ]),
+
+    # Dictionary literal, e.g. [1:1, 2:2, 3:3]
+    Node('DictionaryExpr', kind='Expr',
+         children=[
+             Child('LeftSquare', kind='LeftSquareToken'),
+             Child('Elements', kind='DictionaryElementList'),
+             Child('RightSquare', kind='RightSquareToken'),
+         ]),
+
     # function-call-argument -> label? ':'? expression ','?
     Node('FunctionCallArgument', kind='Syntax',
          children=[
@@ -101,6 +141,22 @@
                    is_optional=True),
          ]),
 
+    # element inside an array expression: expression ','?
+    Node('ArrayElement', kind='Syntax',
+         children=[
+             Child('Expression', kind='Expr'),
+             Child('TrailingComma', kind='CommaToken', is_optional=True),
+         ]),
+
+    # element inside an array expression: expression ','?
+    Node('DictionaryElement', kind='Syntax',
+         children=[
+             Child('KeyExpression', kind='Expr'),
+             Child('Colon', kind='ColonToken'),
+             Child('ValueExpression', kind='Expr'),
+             Child('TrailingComma', kind='CommaToken', is_optional=True),
+         ]),
+
     # An integer literal.
     # 3
     # +3_400
@@ -115,5 +171,25 @@
     Node('StringLiteralExpr', kind='Expr',
          children=[
              Child("StringLiteral", kind='StringLiteralToken')
-         ])
+         ]),
+
+    # true or false
+    Node('BooleanLiteralExpr', kind='Expr',
+         children=[
+             Child("BooleanLiteral", kind='Token',
+                   token_choices=[
+                       'TrueToken',
+                       'FalseToken',
+                   ])
+         ]),
+
+    # a ? 1 : 0
+    Node('TernaryExpr', kind='Expr',
+         children=[
+             Child("ConditionExpression", kind='Expr'),
+             Child("QuestionMark", kind='InfixQuestionMarkToken'),
+             Child("FirstChoice", kind='Expr'),
+             Child("ColonMark", kind='ColonToken'),
+             Child("SecondChoice", kind='Expr')
+         ]),
 ]
diff --git a/utils/update_checkout.py b/utils/update_checkout.py
index df10b57..8221365 100755
--- a/utils/update_checkout.py
+++ b/utils/update_checkout.py
@@ -479,6 +479,14 @@
                                                             skip_history,
                                                             skip_repo_list)
 
+    # Quick check whether somebody is calling update in an empty directory
+    directory_contents = os.listdir(SWIFT_SOURCE_ROOT)
+    if not ('cmark' in directory_contents or 
+            'llvm' in directory_contents or
+            'clang' in directory_contents):
+        print("You don't have all swift sources. "
+              "Call this script with --clone to get them.")
+
     update_results = update_all_repositories(args, config, scheme,
                                              cross_repos_pr)
     fail_count = 0
diff --git a/validation-test/Evolution/Inputs/class_add_virtual_method.swift b/validation-test/Evolution/Inputs/class_add_virtual_method.swift
new file mode 100644
index 0000000..28df044
--- /dev/null
+++ b/validation-test/Evolution/Inputs/class_add_virtual_method.swift
@@ -0,0 +1,43 @@
+
+public func getVersion() -> Int {
+#if BEFORE
+  return 0
+#else
+  return 1
+#endif
+}
+
+#if BEFORE
+
+public class AddVirtualMethod {
+  public init() {}
+
+  public func firstMethod() -> Int {
+    return 1
+  }
+
+  public func secondMethod() -> Int {
+    return 2
+  }
+}
+
+#else
+
+public class AddVirtualMethod {
+  // Note: methods were re-ordered, new method added in the middle
+  public func secondMethod() -> Int {
+    return 2
+  }
+
+  public func thirdMethod() -> Int {
+    return 3
+  }
+
+  public func firstMethod() -> Int {
+    return 1
+  }
+
+  public init() {}
+}
+
+#endif
diff --git a/validation-test/Evolution/test_class_add_virtual_method.swift b/validation-test/Evolution/test_class_add_virtual_method.swift
new file mode 100644
index 0000000..dfa4084
--- /dev/null
+++ b/validation-test/Evolution/test_class_add_virtual_method.swift
@@ -0,0 +1,19 @@
+// RUN: %target-resilience-test
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import class_add_virtual_method
+
+
+var ClassAddVirtualMethodTest = TestSuite("ClassAddVirtualMethod")
+
+ClassAddVirtualMethodTest.test("ClassAddVirtualMethod") {
+  let c = AddVirtualMethod()
+
+  do {
+    expectEqual(1, c.firstMethod())
+    expectEqual(2, c.secondMethod())
+  }
+}
+
+runAllTests()
diff --git a/validation-test/Reflection/functions.swift b/validation-test/Reflection/functions.swift
index 3b4e0b2..8786247 100644
--- a/validation-test/Reflection/functions.swift
+++ b/validation-test/Reflection/functions.swift
@@ -26,8 +26,8 @@
 // CHECK-NEXT:    (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -45,8 +45,8 @@
 // CHECK-NEXT:    (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=metadata offset=12
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -85,8 +85,8 @@
 // CHECK-NEXT:    (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -103,12 +103,12 @@
 // CHECK-NEXT:    (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36
+// CHECK-32-NEXT:   (field offset=24
+// CHECK-32-NEXT:     (reference kind=strong refcounting=native))
 // CHECK-32-NEXT:   (field offset=28
 // CHECK-32-NEXT:     (reference kind=strong refcounting=native))
 // CHECK-32-NEXT:   (field offset=32
-// CHECK-32-NEXT:     (reference kind=strong refcounting=native))
-// CHECK-32-NEXT:   (field offset=36
 // CHECK-32-NEXT:     (reference kind=strong refcounting=native)))
 
 // CHECK-64:      Type info:
@@ -132,14 +132,14 @@
 // CHECK-NEXT:    (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT:   (field offset=8
+// CHECK-32-NEXT:     (reference kind=strong refcounting=native))
 // CHECK-32-NEXT:   (field offset=12
 // CHECK-32-NEXT:     (reference kind=strong refcounting=native))
 // CHECK-32-NEXT:   (field offset=16
 // CHECK-32-NEXT:     (reference kind=strong refcounting=native))
 // CHECK-32-NEXT:   (field offset=20
-// CHECK-32-NEXT:     (reference kind=strong refcounting=native))
-// CHECK-32-NEXT:   (field offset=24
 // CHECK-32-NEXT:     (reference kind=strong refcounting=native)))
 
 // CHECK-64:      Type info:
@@ -171,7 +171,7 @@
   // CHECK-32: (class functions.CapturingClass)
   
   // CHECK-32: Type info:
-  // CHECK-32: (class_instance size=12 alignment=1 stride=12
+  // CHECK-32: (class_instance size=8 alignment=1 stride=8
   @_semantics("optimize.sil.never")
   func arity0Capture1() -> () -> () {
     let closure = {
@@ -204,8 +204,8 @@
   // CHECK-32: (builtin Builtin.NativeObject)
 
   // CHECK-32:        Type info:
-  // CHECK-32:        (closure_context size=32 alignment=8 stride=32
-  // CHECK-32-NEXT:   (field offset=16
+  // CHECK-32:        (closure_context size=24 alignment=8 stride=24
+  // CHECK-32-NEXT:   (field offset=8
   // CHECK-32-NEXT:     (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
   // CHECK-32-NEXT:       (field offset=0
   // CHECK-32-NEXT:         (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -245,8 +245,8 @@
   // CHECK-32: (builtin Builtin.NativeObject)
   
   // CHECK-32:        Type info:
-  // CHECK-32:        (closure_context size=20 alignment=4 stride=20
-  // CHECK-32-NEXT:   (field offset=12
+  // CHECK-32:        (closure_context size=16 alignment=4 stride=16
+  // CHECK-32-NEXT:   (field offset=8
   // CHECK-32-NEXT:     (tuple size=8 alignment=4 stride=8 num_extra_inhabitants=0
   // CHECK-32-NEXT:       (field offset=0
   // CHECK-32-NEXT:         (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -283,8 +283,8 @@
   // CHECK-32: (builtin Builtin.NativeObject)
   
   // CHECK-32:        Type info:
-  // CHECK-32:        (closure_context size=16 alignment=4 stride=16
-  // CHECK-32-NEXT:   (field offset=12
+  // CHECK-32:        (closure_context size=12 alignment=4 stride=12
+  // CHECK-32-NEXT:   (field offset=8
   // CHECK-32-NEXT:     (single_payload_enum size=4 alignment=4 stride=4 num_extra_inhabitants=4095
   // CHECK-32-NEXT:       (field name=some offset=0
   // CHECK-32-NEXT:         (class_existential size=4 alignment=4 stride=4 num_extra_inhabitants=4096
@@ -326,7 +326,7 @@
 
   // CHECK-32:        Type info:
   // CHECK-32:        (closure_context size=32 alignment=8 stride=32
-  // CHECK-32-NEXT:   (field offset=12
+  // CHECK-32-NEXT:   (field offset=8
   // CHECK-32-NEXT:     (reference kind=strong refcounting=native))
   // CHECK-32-NEXT:   (field offset=16
   // CHECK-32-NEXT:     (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -367,10 +367,10 @@
   // CHECK-32: (builtin Builtin.NativeObject)
   
   // CHECK-32: Type info:
-  // CHECK-32: (closure_context size=20 alignment=4 stride=20
-  // CHECK-32:   (field offset=12
+  // CHECK-32: (closure_context size=16 alignment=4 stride=16
+  // CHECK-32:   (field offset=8
   // CHECK-32:     (reference kind=strong refcounting=native))
-  // CHECK-32:   (field offset=16
+  // CHECK-32:   (field offset=12
   // CHECK-32:     (reference kind=strong refcounting=native)))
   @_semantics("optimize.sil.never")
   func arity1Capture2() -> (Int) -> () {
@@ -408,7 +408,7 @@
   
   // CHECK-32: Type info:
   // CHECK-32: (closure_context size=32 alignment=8 stride=32
-  // CHECK-32:   (field offset=12
+  // CHECK-32:   (field offset=8
   // CHECK-32:     (reference kind=strong refcounting=native))
   // CHECK-32:   (field offset=16
   // CHECK-32:     (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -457,7 +457,7 @@
   
   // CHECK-32: Type info:
   // CHECK-32: (closure_context size=32 alignment=8 stride=32
-  // CHECK-32:   (field offset=12
+  // CHECK-32:   (field offset=8
   // CHECK-32:     (reference kind=strong refcounting=native))
   // CHECK-32:   (field offset=16
   // CHECK-32:     (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -510,8 +510,8 @@
 // CHECK-32: (builtin Builtin.NativeObject)
 
 // CHECK-32:        Type info:
-// CHECK-32:        (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32:        (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (reference kind=weak refcounting=native)))
 
 reflect(function: C().captureUnownedSelf())
@@ -531,8 +531,8 @@
 // CHECK-32: (builtin Builtin.NativeObject)
 
 // CHECK-32:        Type info:
-// CHECK-32:        (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32:        (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (reference kind=unowned refcounting=native)))
 
 doneReflecting()
diff --git a/validation-test/Reflection/functions_objc.swift b/validation-test/Reflection/functions_objc.swift
index dd56664..8e05508 100644
--- a/validation-test/Reflection/functions_objc.swift
+++ b/validation-test/Reflection/functions_objc.swift
@@ -15,16 +15,16 @@
 // CHECK-32-NEXT: (builtin Builtin.NativeObject)
 
 // CHECK-32:      Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40 num_extra_inhabitants=0
-// CHECK-32-NEXT:   (field offset=12
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36 num_extra_inhabitants=0
+// CHECK-32-NEXT:   (field offset=8
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field offset=16
+// CHECK-32-NEXT:   (field offset=12
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT:   (field offset=20
+// CHECK-32-NEXT:   (field offset=16
 // CHECK-32-NEXT:     (builtin size=16 alignment=4 stride=16 num_extra_inhabitants=0))
-// CHECK-32-NEXT:   (field offset=36
+// CHECK-32-NEXT:   (field offset=32
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown)))
 
 // CHECK-64:      Type reference:
diff --git a/validation-test/Reflection/inherits_Swift.swift b/validation-test/Reflection/inherits_Swift.swift
index 67a1c50..7b0aa77 100644
--- a/validation-test/Reflection/inherits_Swift.swift
+++ b/validation-test/Reflection/inherits_Swift.swift
@@ -37,12 +37,12 @@
 // CHECK-32: (class inherits_Swift.BaseClass)
 
 // CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=17 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32-NEXT:   (field name=w offset=12
+// CHECK-32-NEXT: (class_instance size=13 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT:   (field name=w offset=8
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=x offset=16
+// CHECK-32-NEXT:   (field name=x offset=12
 // CHECK-32-NEXT:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
@@ -73,12 +73,12 @@
 // CHECK-32: (class inherits_Swift.DerivedClass)
 
 // CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT:   (field name=y offset=17
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
+// CHECK-32-NEXT:   (field name=y offset=13
 // CHECK-32-NEXT:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT:   (field name=z offset=20
+// CHECK-32-NEXT:   (field name=z offset=16
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Array.swift b/validation-test/Reflection/reflect_Array.swift
index c8b84e7..01996e3 100644
--- a/validation-test/Reflection/reflect_Array.swift
+++ b/validation-test/Reflection/reflect_Array.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_Array.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
 // (unstable implementation details omitted)
 
diff --git a/validation-test/Reflection/reflect_Bool.swift b/validation-test/Reflection/reflect_Bool.swift
index 9cabb01..7f0fe57 100644
--- a/validation-test/Reflection/reflect_Bool.swift
+++ b/validation-test/Reflection/reflect_Bool.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Bool.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
diff --git a/validation-test/Reflection/reflect_Character.swift b/validation-test/Reflection/reflect_Character.swift
index d6911ed..cb05d37 100644
--- a/validation-test/Reflection/reflect_Character.swift
+++ b/validation-test/Reflection/reflect_Character.swift
@@ -42,8 +42,8 @@
 // CHECK-32: (class reflect_Character.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT:   (field name=t offset=16
+// CHECK-32-NEXT: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT:   (field name=t offset=8
 // CHECK-32-NEXT:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_representation offset=0
 // CHECK-32-NEXT:         (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
diff --git a/validation-test/Reflection/reflect_Dictionary.swift b/validation-test/Reflection/reflect_Dictionary.swift
index 2eecc2d..5a33cdf 100644
--- a/validation-test/Reflection/reflect_Dictionary.swift
+++ b/validation-test/Reflection/reflect_Dictionary.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_Dictionary.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // (unstable implementation details omitted)
 
diff --git a/validation-test/Reflection/reflect_Double.swift b/validation-test/Reflection/reflect_Double.swift
index 80904ed..f95deee 100644
--- a/validation-test/Reflection/reflect_Double.swift
+++ b/validation-test/Reflection/reflect_Double.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Double.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Float.swift b/validation-test/Reflection/reflect_Float.swift
index d59b985..fec3513 100644
--- a/validation-test/Reflection/reflect_Float.swift
+++ b/validation-test/Reflection/reflect_Float.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Float.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int.swift b/validation-test/Reflection/reflect_Int.swift
index a8b8488..056943b 100644
--- a/validation-test/Reflection/reflect_Int.swift
+++ b/validation-test/Reflection/reflect_Int.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Int.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int16.swift b/validation-test/Reflection/reflect_Int16.swift
index d51a0e1..3818d73 100644
--- a/validation-test/Reflection/reflect_Int16.swift
+++ b/validation-test/Reflection/reflect_Int16.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Int16.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int32.swift b/validation-test/Reflection/reflect_Int32.swift
index a2d642e..26da3ae 100644
--- a/validation-test/Reflection/reflect_Int32.swift
+++ b/validation-test/Reflection/reflect_Int32.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Int32.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int64.swift b/validation-test/Reflection/reflect_Int64.swift
index d1a1c1b..9ef651c 100644
--- a/validation-test/Reflection/reflect_Int64.swift
+++ b/validation-test/Reflection/reflect_Int64.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Int64.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int8.swift b/validation-test/Reflection/reflect_Int8.swift
index b79ff1f..fd8db13 100644
--- a/validation-test/Reflection/reflect_Int8.swift
+++ b/validation-test/Reflection/reflect_Int8.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_Int8.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_NSArray.swift b/validation-test/Reflection/reflect_NSArray.swift
index 7abeb2c..f0d735a 100644
--- a/validation-test/Reflection/reflect_NSArray.swift
+++ b/validation-test/Reflection/reflect_NSArray.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_NSArray.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (reference kind=strong refcounting=unknown)))
 
 doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSNumber.swift b/validation-test/Reflection/reflect_NSNumber.swift
index 4f8c3f8..e80fd09 100644
--- a/validation-test/Reflection/reflect_NSNumber.swift
+++ b/validation-test/Reflection/reflect_NSNumber.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_NSNumber.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (reference kind=strong refcounting=unknown)))
 
 doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSSet.swift b/validation-test/Reflection/reflect_NSSet.swift
index f0c1f5c..5704edb 100644
--- a/validation-test/Reflection/reflect_NSSet.swift
+++ b/validation-test/Reflection/reflect_NSSet.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_NSSet.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (reference kind=strong refcounting=unknown)))
 
 doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSString.swift b/validation-test/Reflection/reflect_NSString.swift
index ee02334..ab8fa0c 100644
--- a/validation-test/Reflection/reflect_NSString.swift
+++ b/validation-test/Reflection/reflect_NSString.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_NSString.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (reference kind=strong refcounting=unknown)))
 
 doneReflecting()
diff --git a/validation-test/Reflection/reflect_Set.swift b/validation-test/Reflection/reflect_Set.swift
index dcfb477..267bd21 100644
--- a/validation-test/Reflection/reflect_Set.swift
+++ b/validation-test/Reflection/reflect_Set.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_Set.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // (unstable implementation details omitted)
 
diff --git a/validation-test/Reflection/reflect_String.swift b/validation-test/Reflection/reflect_String.swift
index 2e8dde6..2941249 100644
--- a/validation-test/Reflection/reflect_String.swift
+++ b/validation-test/Reflection/reflect_String.swift
@@ -34,8 +34,8 @@
 // CHECK-32: (class reflect_String.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24
-// CHECK-32-NEXT:   (field name=t offset=12
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20
+// CHECK-32-NEXT:   (field name=t offset=8
 // CHECK-32-NEXT:     (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
 // (unstable implementation details omitted)
 
diff --git a/validation-test/Reflection/reflect_UInt.swift b/validation-test/Reflection/reflect_UInt.swift
index 3f951d3..94309fb 100644
--- a/validation-test/Reflection/reflect_UInt.swift
+++ b/validation-test/Reflection/reflect_UInt.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_UInt.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt16.swift b/validation-test/Reflection/reflect_UInt16.swift
index 8d9ee6b..d7ec13b 100644
--- a/validation-test/Reflection/reflect_UInt16.swift
+++ b/validation-test/Reflection/reflect_UInt16.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_UInt16.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt32.swift b/validation-test/Reflection/reflect_UInt32.swift
index 4fd5dcd..5123abd 100644
--- a/validation-test/Reflection/reflect_UInt32.swift
+++ b/validation-test/Reflection/reflect_UInt32.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_UInt32.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt64.swift b/validation-test/Reflection/reflect_UInt64.swift
index 2c8248a..6e672df 100644
--- a/validation-test/Reflection/reflect_UInt64.swift
+++ b/validation-test/Reflection/reflect_UInt64.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_UInt64.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt8.swift b/validation-test/Reflection/reflect_UInt8.swift
index e02710a..4f94618 100644
--- a/validation-test/Reflection/reflect_UInt8.swift
+++ b/validation-test/Reflection/reflect_UInt8.swift
@@ -35,8 +35,8 @@
 // CHECK-32: (class reflect_UInt8.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
 // CHECK-32:       (field name=_value offset=0
 // CHECK-32:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_empty_class.swift b/validation-test/Reflection/reflect_empty_class.swift
index 1f337fe..6c54d94 100644
--- a/validation-test/Reflection/reflect_empty_class.swift
+++ b/validation-test/Reflection/reflect_empty_class.swift
@@ -26,7 +26,7 @@
 // CHECK-32: (class reflect_empty_class.EmptyClass)
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=12 alignment=1 stride=12 num_extra_inhabitants=0)
+// CHECK-32: (class_instance size=8 alignment=1 stride=8 num_extra_inhabitants=0)
 
 doneReflecting()
 
diff --git a/validation-test/Reflection/reflect_existential.swift b/validation-test/Reflection/reflect_existential.swift
index 1247dc6..a871580 100644
--- a/validation-test/Reflection/reflect_existential.swift
+++ b/validation-test/Reflection/reflect_existential.swift
@@ -37,8 +37,8 @@
 // CHECK-32:   (protocol_composition))
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
 // CHECK-32:       (field name=metadata offset=12
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -65,8 +65,8 @@
 // CHECK-32:     (protocol reflect_existential.P)))
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=32 alignment=4 stride=32 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (opaque_existential size=20 alignment=4 stride=20 num_extra_inhabitants=0
 // CHECK-32:       (field name=metadata offset=12
 // CHECK-32:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096))
@@ -95,8 +95,8 @@
 // CHECK-32:     (protocol reflect_existential.P)))
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
 // CHECK-32:       (field name=object offset=0
 // CHECK-32:         (reference kind=strong refcounting=unknown))
@@ -125,8 +125,8 @@
 // CHECK-32:     (protocol reflect_existential.CP)))
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
 // CHECK-32:       (field name=object offset=0
 // CHECK-32:         (reference kind=strong refcounting=unknown))
@@ -157,8 +157,8 @@
 // CHECK-32:     (protocol reflect_existential.P)))
 
 // CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32:   (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32:   (field name=t offset=8
 // CHECK-32:     (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
 // CHECK-32:       (field name=object offset=0
 // CHECK-32:         (reference kind=strong refcounting=native))
diff --git a/validation-test/Reflection/reflect_multiple_types.swift b/validation-test/Reflection/reflect_multiple_types.swift
index bdcfba9..c477b22 100644
--- a/validation-test/Reflection/reflect_multiple_types.swift
+++ b/validation-test/Reflection/reflect_multiple_types.swift
@@ -205,15 +205,15 @@
 // CHECK-32: (class reflect_multiple_types.TestClass)
 
 // CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=129 alignment=8 stride=136 num_extra_inhabitants=0
-// CHECK-32-NEXT:   (field name=t00 offset=12
+// CHECK-32-NEXT: (class_instance size=121 alignment=8 stride=128 num_extra_inhabitants=0
+// CHECK-32-NEXT:   (field name=t00 offset=8
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
 // (unstable implementation details omitted)
-// CHECK-32:   (field name=t01 offset=16
+// CHECK-32:   (field name=t01 offset=12
 // CHECK-32-NEXT:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT:   (field name=t02 offset=24
+// CHECK-32-NEXT:   (field name=t02 offset=16
 // CHECK-32-NEXT:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_representation offset=0
 // CHECK-32-NEXT:         (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
@@ -223,68 +223,68 @@
 // CHECK-32-NEXT:             (struct size=4 alignment=4 stride=4 num_extra_inhabitants=4096
 // CHECK-32-NEXT:               (field name=_nativeBuffer offset=0
 // CHECK-32-NEXT:                 (reference kind=strong refcounting=native))))))
-// CHECK-32-NEXT:   (field name=t03 offset=32
+// CHECK-32-NEXT:   (field name=t03 offset=24
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // (unstable implementation details omitted)
-// CHECK-32:   (field name=t04 offset=40
+// CHECK-32:   (field name=t04 offset=32
 // CHECK-32-NEXT:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t05 offset=48
+// CHECK-32-NEXT:   (field name=t05 offset=40
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t06 offset=52
+// CHECK-32-NEXT:   (field name=t06 offset=44
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t07 offset=56
+// CHECK-32-NEXT:   (field name=t07 offset=48
 // CHECK-32-NEXT:     (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t08 offset=60
+// CHECK-32-NEXT:   (field name=t08 offset=52
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t09 offset=64
+// CHECK-32-NEXT:   (field name=t09 offset=56
 // CHECK-32-NEXT:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t10 offset=72
+// CHECK-32-NEXT:   (field name=t10 offset=64
 // CHECK-32-NEXT:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t11 offset=76
+// CHECK-32-NEXT:   (field name=t11 offset=68
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT:   (field name=t12 offset=80
+// CHECK-32-NEXT:   (field name=t12 offset=72
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT:   (field name=t13 offset=84
+// CHECK-32-NEXT:   (field name=t13 offset=76
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT:   (field name=t14 offset=88
+// CHECK-32-NEXT:   (field name=t14 offset=80
 // CHECK-32-NEXT:     (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT:   (field name=t15 offset=92
+// CHECK-32-NEXT:   (field name=t15 offset=84
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // (unstable implementation details omitted)
-// CHECK-32:   (field name=t16 offset=96
+// CHECK-32:   (field name=t16 offset=88
 // CHECK-32-NEXT:     (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
 // (unstable implementation details omitted)
-// CHECK-32:   (field name=t17 offset=108
+// CHECK-32:   (field name=t17 offset=100
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t18 offset=112
+// CHECK-32-NEXT:   (field name=t18 offset=104
 // CHECK-32-NEXT:     (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t19 offset=116
+// CHECK-32-NEXT:   (field name=t19 offset=108
 // CHECK-32-NEXT:     (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t20 offset=120
+// CHECK-32-NEXT:   (field name=t20 offset=112
 // CHECK-32-NEXT:     (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT:   (field name=t21 offset=128
+// CHECK-32-NEXT:   (field name=t21 offset=120
 // CHECK-32-NEXT:     (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
 // CHECK-32-NEXT:       (field name=_value offset=0
 // CHECK-32-NEXT:         (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
deleted file mode 100644
index 30eb21f..0000000
--- a/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-// This source file is part of the Swift.org open source project
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-[(Int
-(Int
-&_
diff --git a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
index ec99b6a..b4378e9 100644
--- a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
+++ b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
@@ -6,5 +6,4 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
 class a<T where g:d{class A{class A<T>:A{init(){T{
diff --git a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
index e48931e..359453f 100644
--- a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
+++ b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
@@ -6,5 +6,4 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
 struct c{class A:A{}var f=A.s
diff --git a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
index 63fe9ac..dcbf097 100644
--- a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
+++ b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
@@ -6,5 +6,4 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
 struct B{let d=A.b}class A:A{let a=V
diff --git a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
index 00f45d8..f65282f 100644
--- a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
+++ b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
@@ -6,5 +6,4 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
 {guard let{protocol A{extension{let d}}}let f=d
diff --git a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift b/validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
similarity index 86%
rename from validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
rename to validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
index 97abd53..4b95974 100644
--- a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
+++ b/validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
@@ -5,5 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 [.h=_
diff --git a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
index e546946..73f5994 100644
--- a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
+++ b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
@@ -6,5 +6,4 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
 &[_=(&_
diff --git a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
index 8be1db1..5d42a2b 100644
--- a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
diff --git a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
index 8f0ba7d..ee5d02c 100644
--- a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
+++ b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 typealias e:a
 struct A:a{}typealias a=A
diff --git a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
index 9b66b76..9e30b6b 100644
--- a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
+++ b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{class a:Self.a
diff --git a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
index f54117f..297f82b 100644
--- a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
+++ b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P}extension P{{}typealias a:P}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index f9d112f..d9dc8bd 100644
--- a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 &{LazyFilterIndex{
diff --git a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
index 8d68e87..fea557c 100644
--- a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
+++ b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:a{{}typealias e:a}{}class a:A{typealias e:b
diff --git a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
index d8cfda1..0c7cab3 100644
--- a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{struct A}class a:P{class a:A
diff --git a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
index da91b69..87061d5 100644
--- a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
+++ b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 {class a:P{{}typealias a:Self.a}protocol P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
index 675bf9e..4ee8994 100644
--- a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
+++ b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 @objc protocol P{typealias e:P{}var a}{}extension P{typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
index f14b655..6827b5d 100644
--- a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:A{{}class a{let ca{a{
diff --git a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
index 06b5bb10..b1db627 100644
--- a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
+++ b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:RangeReplaceableCollection
 typealias e:a._=A.init(
diff --git a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
index 24269e6..3edd0b70 100644
--- a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
+++ b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 guard#keyPath($
diff --git a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
index 441f3f5..0a37d63 100644
--- a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
+++ b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 extension in($A
diff --git a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
index 80bca15..db1c2fe 100644
--- a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
+++ b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{typealias e:P{}class a{{}func a:Self.a.e
diff --git a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
index eb3ce30..07b3cad 100644
--- a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
+++ b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 &_ is Character
diff --git a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
index 963d2de..2549064 100644
--- a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
+++ b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 guard let f==A:UnfoldSequence
diff --git a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index a50bb7f..5c7f0d2 100644
--- a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{{}class a:A{}protocol A:P.a{typealias a{}func a:a
diff --git a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index 5eba003..e22a1c3 100644
--- a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 @objc protocol P{struct B{var f=_=a{}}class a{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
index 5b4f0e4..1686b88 100644
--- a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
+++ b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 Indexable
 & ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
index 8c2d8ea..1404712 100644
--- a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
+++ b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{protocol b:P{{}typealias e:a.a}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
index 615f29c..769a13a 100644
--- a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
+++ b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a{@objc@dynamic
 let d
diff --git a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 33a3375..36a9536 100644
--- a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{{}protocol A{typealias e{}}typealias a=A}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
index 26b3ac3..9421946 100644
--- a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{typealias a{}class a
 {}typealias a{}class a
diff --git a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 1900ef7..57f8aaf 100644
--- a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a:A
 protocol A:a{
diff --git a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
index af99a3f..34901f3 100644
--- a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
+++ b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 extension P{{}}protocol P{protocol P{protocol A{{}typealias a{}}typealias e:A.a}typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
index f0e4bf6..08c38fe 100644
--- a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
+++ b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{
 typealias e:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
index 7fd018a..aa5c573 100644
--- a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:A{struct B{{}var a{class a{class ss:a
diff --git a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index efc3af8..0374eed 100644
--- a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:RangeReplaceableCollection
 protocol P{
diff --git a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index 1714776..54eafc3 100644
--- a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:A.b{func 丏
 protocol b:Collection
diff --git a/validation-test/compiler_crashers_fixed/28796-result-second.swift b/validation-test/compiler_crashers_fixed/28796-result-second.swift
index 316ac8c..41a241c 100644
--- a/validation-test/compiler_crashers_fixed/28796-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28796-result-second.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a<a{{{}}func b{extension{class a<a{{}class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
index df54499..76fd112b 100644
--- a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
+++ b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a<a{protocol A{protocol A{}typealias e where f:A
diff --git a/validation-test/compiler_crashers_fixed/28804-second.swift b/validation-test/compiler_crashers_fixed/28804-second.swift
index edcddea..d2d91d8 100644
--- a/validation-test/compiler_crashers_fixed/28804-second.swift
+++ b/validation-test/compiler_crashers_fixed/28804-second.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a<a{
 protocol A{{}typealias e where f=A
diff --git a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
index 3902655..84fc444 100644
--- a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
+++ b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a:RangeReplaceableCollection}protocol P{{}typealias e:a{{}}typealias e:Collection
diff --git a/validation-test/compiler_crashers_fixed/28808-hasval.swift b/validation-test/compiler_crashers_fixed/28808-hasval.swift
index af52480..d930ac5 100644
--- a/validation-test/compiler_crashers_fixed/28808-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28808-hasval.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{typealias a
 protocol A:P{
diff --git a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 70a1cc5..d951e40 100644
--- a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 {<a.h=a
 class a<H
diff --git a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
index cebc195..28c2d36 100644
--- a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
+++ b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 .a.i(t:&_
diff --git a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
index ac9a4e6..5320203 100644
--- a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A{{}protocol A{func a:Self.a}typealias e:A.a
diff --git a/validation-test/compiler_crashers_fixed/28824-hasval.swift b/validation-test/compiler_crashers_fixed/28824-hasval.swift
index 59b31af..a920a03 100644
--- a/validation-test/compiler_crashers_fixed/28824-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28824-hasval.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 extension CountableRange{protocol b{typealias a:RangeReplaceableCollection
 protocol P{}
diff --git a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
index 1aa2114..71601aa 100644
--- a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
+++ b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol b:a{init(t:a}class a{class a
diff --git a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index cd7ff73..cd937d6 100644
--- a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 [(Int
 (t:&_
diff --git a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
similarity index 84%
copy from validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
copy to validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index 97abd53..768a520 100644
--- a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
+++ b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,5 +5,7 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-[.h=_
+// RUN: not %target-swift-frontend %s -emit-ir
+[(Int
+(Int
+&_
diff --git a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
index 73776c4..522b887 100644
--- a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 extension CountableRange{{}class a:a&a.a{func a
diff --git a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
index f0dbe14..c20b4e1 100644
--- a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 class a<a{
 class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 392b757..b7b0294 100644
--- a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{typealias e:A
 protocol A:P{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28842-hasval.swift b/validation-test/compiler_crashers_fixed/28842-hasval.swift
index 0a745b8..12fd071 100644
--- a/validation-test/compiler_crashers_fixed/28842-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28842-hasval.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{{}typealias a:A{}class a
 protocol a protocol A:P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
index 504f8d5..2acdaaa 100644
--- a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
+++ b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{typealias a{}func a:a.a{}class a{{}protocol 0
diff --git a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 350c824..3b62d6e 100644
--- a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:a{{}typealias a=a{}func a{}typealias a}class a:A{func a
diff --git a/validation-test/compiler_crashers_fixed/28853-result-second.swift b/validation-test/compiler_crashers_fixed/28853-result-second.swift
index 122c6ef..d2c10e9 100644
--- a/validation-test/compiler_crashers_fixed/28853-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28853-result-second.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 func a<a{
 extension{{}
diff --git a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index 14d2e3d..fcf87c7 100644
--- a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol A:RangeReplaceableCollection&a:class a:A
diff --git a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
similarity index 83%
rename from validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
rename to validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
index 026a0b1..f05671c 100644
--- a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
+++ b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
@@ -5,8 +5,7 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 func a
 class a<b}let d=a?as?CVarArg
 & a
diff --git a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
similarity index 84%
rename from validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
rename to validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
index 0442f6c..ca51a8b 100644
--- a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
+++ b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
@@ -5,8 +5,7 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 class a
 class a<a{{}class a<a{var f=a
 & ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
index 40f673d..f78be0e 100644
--- a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
+++ b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
@@ -5,7 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
 // RUN: not %target-swift-frontend %s -emit-ir
 protocol P{class a}protocol A:P
 extension P.a:A
diff --git a/validation-test/stdlib/FloatingPointConversion.swift.gyb b/validation-test/stdlib/FloatingPointConversion.swift.gyb
index 9882102..3a96da7 100644
--- a/validation-test/stdlib/FloatingPointConversion.swift.gyb
+++ b/validation-test/stdlib/FloatingPointConversion.swift.gyb
@@ -115,75 +115,59 @@
 
 %  end # for in all_floating_point_types (Other)
 
-%{
-
-float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion",
-"""
-% for int_ty in all_integer_types(word_bits):
-%  OtherInt = int_ty.stdlib_name
-%  OtherMin = int_ty.min
-%  OtherMax = int_ty.max
-%  (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed)
-
-%  for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]:
-
-%    if testValue < OtherMin or testValue > OtherMax: 
-%          # Can't construct `other` value, do nothing and continue.
-
-%    elif testValue >= FloatMin and testValue <= FloatMax:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") {
-  expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue})
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") {
-  expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue})
-}
-
-%    else:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") {
-  let value: ${OtherInt} = ${testValue}
-  let result = ${Self}(value)
-  expectNotEqual(${OtherInt}(result), value)
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") {
-  let value: ${OtherInt} = ${testValue}
-  let result = ${Self}(exactly: value)
-  expectEqual(result, ${OtherMin} as ${Self})
-  expectEqual(${OtherInt}(result!), value)
-}
-
-%    end
-
-%  end # testValue in testValues
-%  end # for in all_integer_types (Other)
-""")
-}%
-
 #if arch(i386) || arch(arm)
-
-  ${gyb.execute_template(
-      float_to_int_conversion_template,
-      word_bits=32,
-      **locals()
-      )}
-
+% int_types = all_integer_types(32)
 #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
-
-  ${gyb.execute_template(
-      float_to_int_conversion_template,
-      word_bits=64,
-      **locals()
-      )}
-
+% int_types = all_integer_types(64)
 #else
-
 _UnimplementedError()
-
 #endif
 
+% for int_ty in int_types:
+%  OtherInt = int_ty.stdlib_name
+
+extension ${OtherInt} {
+  static var _test${Self}Conversion: [(${OtherInt}, ${OtherInt}, ${OtherInt}?)] {
+    if bitWidth > ${Self}.significandBitCount + 1 {
+      let bitOffset = ${Self}.significandBitCount + 1
+      let limit: ${OtherInt} = ~(~0 << bitOffset)
+      let over: ${OtherInt} = 1 + limit << 1
+      return [
+        (0, 0, 0),
+        (limit, limit, limit),
+        (over, over + 1, nil),
+%   if int_ty.is_signed:
+        (-limit, -limit, -limit),
+        (-over, -(over + 1), nil),
+%   end
+      ]
+    } else {
+      return [
+        (0, 0, 0),
+        (.min, .min, .min),
+        (.max, .max, .max),
+      ]
+    }
+  }
+}
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}")
+  .forEach(in: ${OtherInt}._test${Self}Conversion) {
+    value, roundedExpectation, exactExpectation in
+
+  let roundedResult = ${Self}(value)
+  expectEqual(roundedResult, ${Self}(roundedExpectation))
+
+  let exactResult = ${Self}(exactly: value)
+  if let expectation = exactExpectation {
+    expectEqual(exactResult!, ${Self}(expectation))
+  } else {
+    expectNil(exactResult)
+  }
+}
+
+%  end # for in int_types
+
 %  if Self == 'Float80':
 #endif
 %  end
diff --git a/validation-test/stdlib/ModelIO.swift b/validation-test/stdlib/ModelIO.swift
index 6272a35..9ffeb4a 100644
--- a/validation-test/stdlib/ModelIO.swift
+++ b/validation-test/stdlib/ModelIO.swift
@@ -3,6 +3,11 @@
 // UNSUPPORTED: OS=watchos
 // REQUIRES: objc_interop
 
+// Currently crashes on iphonesimulator.
+// rdar://35490456
+// UNSUPPORTED: OS=ios
+// UNSUPPORTED: OS=tvos
+
 import StdlibUnittest
 
 import Foundation
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 3e99a47..29eae21 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -516,7 +516,7 @@
             let float = (number!) as? Float
             let expectedFloat = Float(uint32!)
             // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+            if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
                 testFloat(expectedFloat, float)
             }
             
@@ -652,16 +652,16 @@
             let uint = (number!) as? UInt
             expectEqual(UInt(exactly: interestingValue), uint)
 
-            // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
-                let float = (number!) as? Float
-                let expectedFloat = Float(uint!)
-                testFloat(expectedFloat, float)
+            let float = (number!) as? Float
+            let expectedFloat = Float(exactly: uint!)
+            if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+              expectNil(expectedFloat)
+            } else {
+              testFloat(expectedFloat, float)
             }
-            
-            
+
             let double = (number!) as? Double
-            let expectedDouble = Double(uint!)
+            let expectedDouble = Double(exactly: uint!)
             testDouble(expectedDouble, double)
         }
         let bridged = interestingValue as NSNumber