Merge pull request #12898 from sashabelonogov/sashabelonogov/SR-6361

[SR-6361] Fix Data.withUnsafeMutableBytes() for slices with length < range.lowerBound
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/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/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 d9fc118..26e8b05 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -299,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 ab1b13a..5be9bbc 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2225,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.
   ///
@@ -3402,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/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 e64b60b..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,
@@ -3705,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/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/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/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/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/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 db3c8f6..ce4b982 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -299,15 +299,15 @@
   /// The module for which we should verify all of the generic signatures.
   std::string VerifyGenericSignaturesInModule;
 
-  enum ActionType {
-    NoneAction, ///< No specific action
-    Parse, ///< Parse only
-    Typecheck, ///< Parse and type-check only
-    DumpParse, ///< Parse only and dump AST
+  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,
@@ -316,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/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 29ec7b3..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;
 };
 
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/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index b6184c8..27a8a51 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -1237,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(
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 572f2f3..efbd741 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -171,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;
@@ -479,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/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index b87fdd4..d27792d 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -156,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)>>>;
@@ -200,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
@@ -214,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();
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 75f1f4e..370b432 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -275,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,
@@ -290,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,
@@ -298,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,
@@ -317,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,
@@ -332,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/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 7993440..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 = 384; // Last change: begin_apply
+const uint16_t VERSION_MINOR = 385; // Last change: Optimization attribute
 
 using DeclIDField = BCFixed<31>;
 
@@ -1401,6 +1401,11 @@
     BCFixed<2>  // inline value
   >;
 
+  using OptimizeDeclAttrLayout = BCRecordLayout<
+    Optimize_DECL_ATTR,
+    BCFixed<2>  // optimize value
+  >;
+
   // Encodes a VersionTuple:
   //
   //  Major
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 08f8372..e9f7c09 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -54,6 +54,11 @@
   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
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/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/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 483107a..4233676 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2184,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();
@@ -2689,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);
 
@@ -2699,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/Type.cpp b/lib/AST/Type.cpp
index df753e4..d27e118 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3336,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)
@@ -3363,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.
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/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 9700939..2d1e878 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -238,39 +238,39 @@
   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") {
@@ -300,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");
     }
@@ -319,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;
@@ -335,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)) {
@@ -356,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;
@@ -376,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
@@ -405,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
@@ -429,7 +430,7 @@
       break;
     }
 
-    case FrontendOptions::EmitIR: {
+    case FrontendOptions::ActionType::EmitIR: {
       if (Opts.OutputFilenames.empty())
         Opts.setOutputFilenameToStdout();
       else
@@ -437,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
@@ -474,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;
       }
@@ -542,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,
@@ -566,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;
     }
   }
@@ -664,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;
     }
   }
@@ -1169,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());
@@ -1229,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;
@@ -1292,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).
@@ -1349,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);
@@ -1707,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 90bd29a..d6acb03 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -319,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");
@@ -512,12 +512,12 @@
   FrontendOptions opts = Invocation.getFrontendOptions();
   FrontendOptions::ActionType Action = opts.RequestedAction;
 
-  if (Action == FrontendOptions::EmitSyntax)
+  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();
@@ -581,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) {
@@ -621,7 +621,7 @@
     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();
@@ -632,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()) {
@@ -690,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();
   }
@@ -740,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);
@@ -763,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();
@@ -802,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);
@@ -810,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);
@@ -836,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))
@@ -908,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);
 
@@ -956,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()) {
@@ -974,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;
@@ -984,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.
@@ -1007,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;
@@ -1109,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;
   }
@@ -1210,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";
@@ -1326,7 +1322,7 @@
   }
 
   if (Invocation.getFrontendOptions().RequestedAction ==
-        FrontendOptions::NoneAction) {
+      FrontendOptions::ActionType::NoneAction) {
     Instance->getDiags().diagnose(SourceLoc(),
                                  diag::error_missing_frontend_action);
     return finishDiagProcessing(1);
@@ -1378,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();
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 e2d42f7..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
@@ -941,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;
@@ -1163,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())
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 cbbf2d8..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) {
@@ -825,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();
   });
 }
@@ -1194,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());
@@ -1240,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
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 0cdd56d..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) {
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/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 b025fe7..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);
     
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 24aef2f..ef8f1c8 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1388,7 +1388,7 @@
     cacheVariable = cast<llvm::GlobalVariable>(
         IGM.getAddrOfTypeMetadataLazyCacheVariable(type, ForDefinition));
 
-    if (IGM.getOptions().OptimizeForSize)
+    if (IGM.getOptions().optimizeForSize())
       accessor->addFnAttr(llvm::Attribute::NoInline);
   }
 
@@ -1432,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,
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index c8fe6a4..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");
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 9c1c074..d9bb28c 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1109,7 +1109,7 @@
   if (!accessor->empty())
     return accessor;
 
-  if (IGM.getOptions().OptimizeForSize)
+  if (IGM.getOptions().optimizeForSize())
     accessor->addFnAttr(llvm::Attribute::NoInline);
 
   // Okay, define the accessor.
@@ -1464,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);
@@ -1570,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();
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 d220ebe..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"
@@ -1478,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();
@@ -1490,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);
@@ -1803,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.,
@@ -1838,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);
@@ -1978,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 aa697ff..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) {
@@ -818,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");
@@ -851,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 96337c0..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"
@@ -957,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 042b8ae..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);
@@ -1109,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.
@@ -5107,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/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/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 79c1960..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;
@@ -1390,7 +1405,7 @@
   case tok::integer_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::integer_literal);
-    SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Loc);
+    SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Tok.getLoc());
     Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1398,7 +1413,7 @@
   case tok::floating_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::floating_literal);
-    SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Loc);
+    SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Tok.getLoc());
     Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1428,6 +1443,8 @@
 
   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()));
@@ -1811,7 +1828,7 @@
   Token EntireTok = Tok;
 
   // Create a syntax node for string literal.
-  SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, Tok.getLoc());
+  SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, peekToken().getLoc());
 
   // FIXME: Avoid creating syntax nodes for string interpolation.
   SyntaxParsingContextChild LocalContext(SyntaxContext, /*disabled*/true);
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index 9ff7c0f..9721141 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #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"
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index ee85135..675615d 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -878,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,
@@ -907,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")
@@ -5012,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) ||
@@ -5045,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);
@@ -5173,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) ||
@@ -5216,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;
 
@@ -5565,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;
 
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/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/SILModule.cpp b/lib/SIL/SILModule.cpp
index 3a8b27a..2b41a69 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -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/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index f633882..8a25896 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -2252,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)
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index c48ce35..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();
@@ -754,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/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 3908a97..2252d6c 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -5080,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/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/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index b302875..ac5d62e 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -405,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/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/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index 674f560..1805c17 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -542,62 +542,70 @@
 }
 
 //===----------------------------------------------------------------------===//
-//                          Allocation Optimization
+//                          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);
-  void promoteDestroyAddr(DestroyAddrInst *DAI,
-                          MutableArrayRef<AvailableValue> Values);
-  bool
-  canPromoteDestroyAddr(DestroyAddrInst *DAI,
-                        llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
+  SILModule &getModule() const { return TheMemory->getModule(); }
 
-  // Load promotion.
-  bool hasEscapedAt(SILInstruction *I);
   void updateAvailableValues(SILInstruction *Inst,
                              llvm::SmallBitVector &RequiredElts,
                              SmallVectorImpl<AvailableValue> &Result,
                              llvm::SmallBitVector &ConflictingValues);
-  void computeAvailableValues(SILInstruction *StartingFrom,
-                              llvm::SmallBitVector &RequiredElts,
-                              SmallVectorImpl<AvailableValue> &Result);
   void computeAvailableValuesFrom(
       SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
       llvm::SmallBitVector &RequiredElts,
@@ -605,45 +613,26 @@
       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) {
@@ -659,35 +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(
+void AvailableValueDataflowContext::updateAvailableValues(
     SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
     SmallVectorImpl<AvailableValue> &Result,
     llvm::SmallBitVector &ConflictingValues) {
-
-  // Handle store and assign.
+  // 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 = SI->getSrc()->getType();
 
-    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.
       if (!RequiredElts[StartSubElt+i]) continue;
       
@@ -719,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;
@@ -737,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.
@@ -748,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();
@@ -760,16 +731,9 @@
   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,
+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());
@@ -777,18 +741,44 @@
   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] = {};
+  for (unsigned i :
+       range(FirstEltOffset, FirstEltOffset + NumLoadSubElements)) {
+    AvailableValueIsPresent[i] = Result[i].getValue();
+  }
 
-  return;
+  // 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(
+void AvailableValueDataflowContext::computeAvailableValuesFrom(
     SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
     llvm::SmallBitVector &RequiredElts, SmallVectorImpl<AvailableValue> &Result,
     llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
@@ -862,6 +852,187 @@
   }
 }
 
+/// 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");
+
+  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.
+  }
+
+  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.
+
+  // 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;
+}
+
+//===----------------------------------------------------------------------===//
+//                          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.
@@ -899,7 +1070,7 @@
 
   // 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 = SrcAddr->getType().getObjectType();
@@ -925,28 +1096,17 @@
   
   // 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].getValue()) {
-        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;
@@ -987,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
@@ -1005,13 +1165,12 @@
   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);
-  computeAvailableValues(DAI, RequiredElts, TmpList);
-
-  // If some value is not available at this load point, then we fail.
-  if (llvm::any_of(range(FirstElt, FirstElt + NumLoadSubElements),
-                   [&](unsigned i) -> bool { return !TmpList[i]; }))
+  if (!DataflowContext.computeAvailableValues(DAI, FirstElt, NumLoadSubElements,
+                                              RequiredElts, TmpList))
     return false;
 
   // Now that we have our final list, move the temporary lists contents into
@@ -1051,105 +1210,6 @@
   DAI->eraseFromParent();
 }
 
-/// 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
 /// that is only stored to (after load promotion) then remove it completely.
 bool AllocOptimize::tryToRemoveDeadAllocation() {
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 e5f48b0..3fad2e2 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -489,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/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index f43224d..d1333cd 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -1148,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 abaed72..6b2687c 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -1289,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/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 801dd44..254c6b7 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -555,8 +555,7 @@
 
       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.
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 9f419ba..261512d 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -848,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 9e854a8..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()
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index eb69a59..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;
 
@@ -1841,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/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 2c4fded..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);
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 01d1832..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)
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/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 04f0599..62f9cb5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -4638,7 +4638,7 @@
     if (!IsFirstPass)
       TC.addImplicitConstructors(CD);
 
-    TC.addImplicitDestructor(CD);
+    CD->addImplicitDestructor();
 
     if (!IsFirstPass && !CD->isInvalid())
       TC.checkConformancesInContext(CD, CD);
@@ -6381,6 +6381,7 @@
     UNINTERESTING_ATTR(IBOutlet)
     UNINTERESTING_ATTR(Indirect)
     UNINTERESTING_ATTR(Inline)
+    UNINTERESTING_ATTR(Optimize)
     UNINTERESTING_ATTR(Inlineable)
     UNINTERESTING_ATTR(Effects)
     UNINTERESTING_ATTR(FixedLayout)
@@ -7212,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);
 
@@ -7962,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
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index b5d3c2f..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);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 1a22724..fa1ecae 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1511,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);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index eb824f1..0918a5b 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1277,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,
@@ -1482,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",
@@ -2318,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,
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 1827119..d8e587f 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -407,10 +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;
   SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
-                                isThunk, isGlobal, inlineStrategy, effect,
+                                isThunk, isGlobal, inlineStrategy,
+                                optimizationMode, effect,
                                 numSpecAttrs, hasQualifiedOwnership, funcTyID,
                                 genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
@@ -474,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) {
@@ -2373,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);
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index b861c32..55267a5 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -275,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
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index d8a586b..333ab8f 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2236,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];
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 5b76814..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);
 
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 f57d2361..6a954e6 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -69,6 +69,20 @@
   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 da98f2c..af28b2c 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -111,8 +111,8 @@
   }
 
   // Squash N syntax nodex from the back of the pending list into one.
-  void createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
-                            unsigned N);
+  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; }
@@ -123,6 +123,7 @@
     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);
   }
 
@@ -212,11 +213,23 @@
 }
 
 void SyntaxParsingContext::ContextInfo::
-createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
-                     unsigned N) {
-  auto Size = UsedTokens.size();
+createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse,
+                        unsigned N) {
+  auto Size = NodesToUse.size();
   assert(N && Size >= N);
-  auto Parts = llvm::makeArrayRef(UsedTokens).slice(Size - N);
+  auto Parts = llvm::makeArrayRef(NodesToUse).slice(Size - N);
+
+  // 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;
+    });
+
+  // Remove all pending syntax ndoes that we used to create the new node.
+  for (unsigned I = 0; I < UsedPending; I ++)
+    PendingSyntax.pop_back();
+
+  // Add result to the pending syntax list.
   addPendingSyntax(createSyntaxAs(Parts, Kind));
 }
 
@@ -282,15 +295,15 @@
 }
 
 void SyntaxParsingContextChild::setSyntaxKind(SyntaxKind SKind) {
-  assert(!ContextKind.hasValue());
-  assert(!KnownSyntax.hasValue());
+  assert(!KnownSyntax.hasValue() && "reset");
   KnownSyntax = SKind;
+  ContextKind = None;
 }
 
 void SyntaxParsingContextChild::setContextKind(SyntaxContextKind CKind) {
-  assert(!ContextKind.hasValue());
-  assert(!KnownSyntax.hasValue());
+  assert(!ContextKind.hasValue() && "reset");
   ContextKind = CKind;
+  KnownSyntax = None;
 }
 
 SyntaxParsingContextChild::
@@ -300,12 +313,12 @@
     disable();
 }
 
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) {
+void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc EndLoc) {
   assert(isTopOfContextStack());
   if (!ContextData.Enabled)
     return;
-  auto UsedTokens = ContextData.dropTokenAt(LastTokLoc);
-  UsedTokens = llvm::makeArrayRef(UsedTokens.data(), UsedTokens.size() + 1);
+
+  auto AllNodes = ContextData.collectAllSyntax(EndLoc);
 
   // Create syntax nodes according to the given kind.
   switch (Kind) {
@@ -313,15 +326,17 @@
   case SyntaxKind::IntegerLiteralExpr: {
     // Integer may include the signs before the digits, so check if the sign
     // exists and create.
-    ContextData.createFromBackTokens(Kind, UsedTokens, ContextData.
-      checkTokenFromBack(tok::oper_prefix, UsedTokens, 1) ? 2 : 1);
+    ContextData.createPartiallyFromBack(Kind, AllNodes, ContextData.
+      checkTokenFromBack(tok::oper_prefix, AllNodes, 1) ? 2 : 1);
     break;
   }
+  case SyntaxKind::TernaryExpr:
   case SyntaxKind::StringLiteralExpr: {
-    ContextData.createFromBackTokens(Kind, UsedTokens, 1);
+    auto Pair = SyntaxFactory::countChildren(Kind);
+    assert(Pair.first == Pair.second);
+    ContextData.createPartiallyFromBack(Kind, AllNodes, Pair.first);
     break;
   }
-
   default:
     llvm_unreachable("Unrecognized node kind.");
   }
@@ -334,6 +349,7 @@
   auto EndLoc = Tok.getLoc();
   auto AllNodes = ContextData.collectAllSyntax(EndLoc);
   switch (Kind) {
+  case SyntaxKind::BooleanLiteralExpr:
   case SyntaxKind::NilLiteralExpr:
   case SyntaxKind::DiscardAssignmentExpr:
   case SyntaxKind::IdentifierExpr:
@@ -386,8 +402,21 @@
     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;
   }
 }
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/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/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index 773e7fb..d80b233 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -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/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/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 3861ca5..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
   }
 
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/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/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/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/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/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-remark.swift b/test/Driver/opt-remark.swift
index 433a607..aa2fb52 100644
--- a/test/Driver/opt-remark.swift
+++ b/test/Driver/opt-remark.swift
@@ -38,7 +38,7 @@
 
 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
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 3e206bd..6e32e9c 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -15,7 +15,7 @@
 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')}}
@@ -91,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>())
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/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/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/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/functions.swift b/test/SILGen/functions.swift
index 300bf99..d8d9294 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -452,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/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index cb3ef59..08b07c3 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -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_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index d45f33c..4b1006a 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -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/protocols.swift b/test/SILGen/protocols.swift
index 2f6570d..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]]
 
@@ -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]])
 
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/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/inliner_coldblocks.sil b/test/SILOptimizer/inliner_coldblocks.sil
index 6b378df..58d5c68 100644
--- a/test/SILOptimizer/inliner_coldblocks.sil
+++ b/test/SILOptimizer/inliner_coldblocks.sil
@@ -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/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/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index b7873c1..9751347 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -497,3 +497,25 @@
 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/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/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/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index e429365..3eb5364 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -1,36 +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 bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
-  func bar3(a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
-  func bar4(_ a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></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><IdentifierExpr>
-    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
-    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
-    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
-    bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
-    bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownDecl>
-    var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl><UnknownExpr><IdentifierExpr>
-    foo</IdentifierExpr>()</UnknownExpr>
-  }</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>{<UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<UnknownExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>c:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <UnknownExpr><IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><UnknownExpr><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><UnknownExpr><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr></UnknownExpr><UnknownExpr><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></UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></ArrayElement>]</ArrayExpr></UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></DictionaryElement>]</DictionaryExpr></UnknownExpr><UnknownExpr><IdentifierExpr>
-    foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)</UnknownExpr>
-  }</CodeBlock></UnknownDecl>
-}</UnknownDecl>
+  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 010c211..a9d72bb 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -33,4 +33,11 @@
     _ = ["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_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/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/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/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 1638226..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)
             }
             
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/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/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 616f4f8..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 ?
@@ -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/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 5f30a16..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"
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-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index a04751b..93fce76 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"
@@ -1254,9 +1254,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/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 fcf4122..d6c57e1 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -171,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/test_superclass_methods.swift b/validation-test/Evolution/test_superclass_methods.swift
index e09e8f2..d2434c7 100644
--- a/validation-test/Evolution/test_superclass_methods.swift
+++ b/validation-test/Evolution/test_superclass_methods.swift
@@ -1,9 +1,6 @@
 // RUN: %target-resilience-test
 // REQUIRES: executable_test
 
-// rdar://35492775
-// REQUIRES: swift_test_mode_optimize_none
-
 import StdlibUnittest
 import superclass_methods
 
diff --git a/validation-test/Evolution/test_superclass_properties.swift b/validation-test/Evolution/test_superclass_properties.swift
index bc30df2..81cdf5c 100644
--- a/validation-test/Evolution/test_superclass_properties.swift
+++ b/validation-test/Evolution/test_superclass_properties.swift
@@ -1,9 +1,6 @@
 // RUN: %target-resilience-test
 // REQUIRES: executable_test
 
-// rdar://35492775
-// REQUIRES: swift_test_mode_optimize_none
-
 import StdlibUnittest
 import superclass_properties
 
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_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_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index 5ee0ca9..768a520 100644
--- a/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ b/validation-test/compiler_crashers_fixed/28831-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
 (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/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 61255c4..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)
             }