Index: docs/LangRef.rst
===================================================================
--- docs/LangRef.rst
+++ docs/LangRef.rst
@@ -1427,7 +1427,7 @@
     generated for this function needs to follow certain conventions that
     make it possible for a runtime function to patch over it later.
     The exact effect of this attribute depends on its string value,
-    for which there currently is one legal possiblity:
+    for which there currently are two legal possiblities:
 
      * ``"prologue-short-redirect"`` - This style of patchable
        function is intended to support patching a function prologue to
@@ -1443,6 +1443,24 @@
 
        ``"prologue-short-redirect"`` is currently only supported on
        x86-64.
+     * ``"ms-hotpatch"`` - This style of patchable function is similar to
+       ``"prologue-short-redirect"``, but it also imposes several additional
+       guarantees to support the style of hotpatching used on Windows.  On
+       32-bit x86, the first instruction will be a ``mov %edi, %edi``
+       instruction; this is frequently used as a magic value indicating a
+       hotpatchable function.  On other architectures, however, the first
+       instruction can be anything allowed in a Windows-style prologue;
+       this is because all functions on the non-i386 architectures Windows
+       supports are assumed to be hotpatchable.  Additionally, when not
+       targeting a Visual C++-style toolchain, patch space will be provided
+       prior to the function's entry point of an architecturally specific
+       size.  These sizes are compatible with GCC: on 32-bit x86, the patch
+       space is 64 bytes long; on x86-64, it is 128 bytes long.  The patch
+       space is not provided for MSVC toolchains because the
+       `/FUNCTIONPADMIN <https://msdn.microsoft.com/en-us/library/ms173524.aspx>`_
+       option, which provides this space, is expected to be used there.
+
+       ``"ms-hotpatch"`` is currently only supported on x86 and x86-64.
 
     This attribute by itself does not imply restrictions on
     inter-procedural optimizations.  All of the semantic effects the
Index: include/llvm/Analysis/TargetTransformInfo.h
===================================================================
--- include/llvm/Analysis/TargetTransformInfo.h
+++ include/llvm/Analysis/TargetTransformInfo.h
@@ -23,6 +23,7 @@
 #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
 
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Operator.h"
@@ -36,6 +37,7 @@
 class Function;
 class GlobalValue;
 class Loop;
+class MachineBasicBlock;
 class Type;
 class User;
 class Value;
@@ -295,6 +297,16 @@
   /// target-independent defaults.
   void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
 
+  /// \brief Emit a patchable operation in the given basic block.
+  ///
+  /// Most of the time, this will be a straight-up \c TargetOpcode::PATCHABLE_OP
+  /// instruction, which will be lowered by the target to a no-op that can
+  /// be safely replaced with a short jump. However, some targets under certain
+  /// conditions can have peculiar requirements for this instruction; these
+  /// targets can provide their own implementation of this to emit the correct
+  /// instruction.
+  void emitPatchableOp(StringRef PatchType, MachineBasicBlock &MBB) const;
+
   /// @}
 
   /// \name Scalar Target Information
@@ -631,6 +643,8 @@
   virtual bool isSourceOfDivergence(const Value *V) = 0;
   virtual bool isLoweredToCall(const Function *F) = 0;
   virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
+  virtual void emitPatchableOp(StringRef Kind,
+                               MachineBasicBlock &MBB) const = 0;
   virtual bool isLegalAddImmediate(int64_t Imm) = 0;
   virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
   virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
@@ -769,6 +783,9 @@
   void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override {
     return Impl.getUnrollingPreferences(L, UP);
   }
+  void emitPatchableOp(StringRef Kind, MachineBasicBlock &MBB) const override {
+    return Impl.emitPatchableOp(Kind, MBB);
+  }
   bool isLegalAddImmediate(int64_t Imm) override {
     return Impl.isLegalAddImmediate(Imm);
   }
Index: include/llvm/Analysis/TargetTransformInfoImpl.h
===================================================================
--- include/llvm/Analysis/TargetTransformInfoImpl.h
+++ include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -23,6 +23,10 @@
 #include "llvm/IR/Operator.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Analysis/VectorUtils.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
 
 namespace llvm {
 
@@ -197,6 +201,21 @@
 
   void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {}
 
+  void emitPatchableOp(StringRef, MachineBasicBlock &MBB) const {
+    auto &FirstMI = *MBB.begin();
+
+    auto *TII = MBB.getParent()->getSubtarget().getInstrInfo();
+    auto MIB = BuildMI(MBB, MBB.begin(), FirstMI.getDebugLoc(),
+                       TII->get(TargetOpcode::PATCHABLE_OP))
+                   .addImm(2)
+                   .addImm(FirstMI.getOpcode());
+
+    for (auto &MO : FirstMI.operands())
+      MIB.addOperand(MO);
+
+    FirstMI.eraseFromParent();
+  }
+
   bool isLegalAddImmediate(int64_t Imm) { return false; }
 
   bool isLegalICmpImmediate(int64_t Imm) { return false; }
Index: lib/Analysis/TargetTransformInfo.cpp
===================================================================
--- lib/Analysis/TargetTransformInfo.cpp
+++ lib/Analysis/TargetTransformInfo.cpp
@@ -101,6 +101,11 @@
   return TTIImpl->getUnrollingPreferences(L, UP);
 }
 
+void TargetTransformInfo::emitPatchableOp(
+    StringRef PatchType, MachineBasicBlock &MBB) const {
+  return TTIImpl->emitPatchableOp(PatchType, MBB);
+}
+
 bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
   return TTIImpl->isLegalAddImmediate(Imm);
 }
Index: lib/CodeGen/PatchableFunction.cpp
===================================================================
--- lib/CodeGen/PatchableFunction.cpp
+++ lib/CodeGen/PatchableFunction.cpp
@@ -13,13 +13,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
 
 using namespace llvm;
 
@@ -30,37 +28,34 @@
     initializePatchableFunctionPass(*PassRegistry::getPassRegistry());
   }
 
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
   bool runOnMachineFunction(MachineFunction &F) override;
-   MachineFunctionProperties getRequiredProperties() const override {
+  MachineFunctionProperties getRequiredProperties() const override {
     return MachineFunctionProperties().set(
         MachineFunctionProperties::Property::AllVRegsAllocated);
   }
 };
 }
 
+void PatchableFunction::getAnalysisUsage(AnalysisUsage &AU) const {
+  MachineFunctionPass::getAnalysisUsage(AU);
+  AU.addRequired<TargetTransformInfoWrapperPass>();
+}
+
 bool PatchableFunction::runOnMachineFunction(MachineFunction &MF) {
   if (!MF.getFunction()->hasFnAttribute("patchable-function"))
     return false;
 
-#ifndef NDEBUG
   Attribute PatchAttr = MF.getFunction()->getFnAttribute("patchable-function");
   StringRef PatchType = PatchAttr.getValueAsString();
-  assert(PatchType == "prologue-short-redirect" && "Only possibility today!");
-#endif
+  assert((PatchType == "prologue-short-redirect" ||
+          PatchType == "ms-hotpatch") && "Only possibilities today!");
 
   auto &FirstMBB = *MF.begin();
-  auto &FirstMI = *FirstMBB.begin();
-
-  auto *TII = MF.getSubtarget().getInstrInfo();
-  auto MIB = BuildMI(FirstMBB, FirstMBB.begin(), FirstMI.getDebugLoc(),
-                     TII->get(TargetOpcode::PATCHABLE_OP))
-                 .addImm(2)
-                 .addImm(FirstMI.getOpcode());
-
-  for (auto &MO : FirstMI.operands())
-    MIB.addOperand(MO);
+  const TargetTransformInfo &TTI =
+      getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*MF.getFunction());
+  TTI.emitPatchableOp(PatchType, FirstMBB);
 
-  FirstMI.eraseFromParent();
   MF.ensureAlignment(4);
   return true;
 }
Index: lib/Target/X86/X86AsmPrinter.h
===================================================================
--- lib/Target/X86/X86AsmPrinter.h
+++ lib/Target/X86/X86AsmPrinter.h
@@ -107,6 +107,8 @@
     SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
   }
 
+  void EmitConstantPool() override;
+
   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                        unsigned AsmVariant, const char *ExtraCode,
                        raw_ostream &OS) override;
Index: lib/Target/X86/X86AsmPrinter.cpp
===================================================================
--- lib/Target/X86/X86AsmPrinter.cpp
+++ lib/Target/X86/X86AsmPrinter.cpp
@@ -73,6 +73,31 @@
   return false;
 }
 
+void X86AsmPrinter::EmitConstantPool() {
+  if (MF) {
+    // If an MS hotpatch function, we need to ensure 64 (32-bit) or 128 (64-bit)
+    // bytes of padding precede the label.  This is the scratch space used
+    // by the hotpatching mechanism to insert the patch code.  The movl %edi,
+    // %edi instruction emitted as the very first instruction of a hotpatch
+    // function is usually overwritten with a short jump instruction when the
+    // patch is installed, so it will jump directly into this space.  (But
+    // don't add the space when targeting MSVC.  There, the /FUNCTIONPADMIN
+    // option to link.exe is expected to be used.)
+    const Function *Fn = MF->getFunction();
+    if (!Subtarget->isTargetKnownWindowsMSVC() &&
+        Fn->hasFnAttribute("patchable-function") &&
+        Fn->getFnAttribute("patchable-function").getValueAsString() ==
+            "ms-hotpatch") {
+      // Emit INT3 instructions instead of NOPs. If a patch runs off the end,
+      // best to let the patcher know with a crash/debug break than to silently
+      // continue, only to run into the jump back into the patch.
+      OutStreamer->emitFill(Subtarget->is64Bit() ? 128 : 64, 0xcc);
+    }
+  }
+
+  AsmPrinter::EmitConstantPool();
+}
+
 /// printSymbolOperand - Print a raw symbol reference operand.  This handles
 /// jump tables, constant pools, global address and external symbols, all of
 /// which print to a label with various suffixes for relocation types etc.
Index: lib/Target/X86/X86FrameLowering.cpp
===================================================================
--- lib/Target/X86/X86FrameLowering.cpp
+++ lib/Target/X86/X86FrameLowering.cpp
@@ -927,6 +927,10 @@
   bool NeedsWinCFI = IsWin64Prologue && Fn->needsUnwindTableEntry();
   bool NeedsDwarfCFI =
       !IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry());
+  bool IsMSHotpatch =
+      Fn->hasFnAttribute("patchable-function") &&
+      Fn->getFnAttribute("patchable-function").getValueAsString() ==
+          "ms-hotpatch";
   unsigned FramePtr = TRI->getFrameRegister(MF);
   const unsigned MachineFramePtr =
       STI.isTarget64BitILP32()
@@ -1068,7 +1072,9 @@
     if (!IsWin64Prologue && !IsFunclet) {
       // Update EBP with the new base value.
       BuildMI(MBB, MBBI, DL,
-              TII.get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr),
+              TII.get(IsMSHotpatch ?
+                      (Uses64BitFramePtr ? X86::MOV64rr_REV : X86::MOV32rr_REV):
+                      (Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr)),
               FramePtr)
           .addReg(StackPtr)
           .setMIFlag(MachineInstr::FrameSetup);
Index: lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- lib/Target/X86/X86ISelLowering.cpp
+++ lib/Target/X86/X86ISelLowering.cpp
@@ -2563,10 +2563,13 @@
   X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
   const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();
 
-  const Function *Fn = MF.getFunction();
-  if (Fn->hasExternalLinkage() &&
-      Subtarget.isTargetCygMing() &&
-      Fn->getName() == "main")
+  const Function* Fn = MF.getFunction();
+  if ((Fn->hasExternalLinkage() &&
+       Subtarget.isTargetCygMing() &&
+       Fn->getName() == "main") ||
+      (!Subtarget.is64Bit() && Fn->hasFnAttribute("patchable-function") &&
+       Fn->getFnAttribute("patchable-function").getValueAsString() ==
+           "ms-hotpatch"))
     FuncInfo->setForceFramePointer(true);
 
   MachineFrameInfo *MFI = MF.getFrameInfo();
Index: lib/Target/X86/X86TargetTransformInfo.h
===================================================================
--- lib/Target/X86/X86TargetTransformInfo.h
+++ lib/Target/X86/X86TargetTransformInfo.h
@@ -50,6 +50,12 @@
       : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
         TLI(std::move(Arg.TLI)) {}
 
+  /// \name Generic TTI Implementations
+  /// @{
+  void emitPatchableOp(StringRef PatchType, MachineBasicBlock &MBB) const;
+
+  /// @}
+
   /// \name Scalar TTI Implementations
   /// @{
   TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth);
Index: lib/Target/X86/X86TargetTransformInfo.cpp
===================================================================
--- lib/Target/X86/X86TargetTransformInfo.cpp
+++ lib/Target/X86/X86TargetTransformInfo.cpp
@@ -1608,3 +1608,17 @@
   // correct.
   return (CallerBits & CalleeBits) == CalleeBits;
 }
+
+void X86TTIImpl::emitPatchableOp(StringRef PatchType,
+                                 MachineBasicBlock &MBB) const {
+  if (PatchType != "ms-hotpatch" || !ST->is32Bit()) {
+    BaseT::emitPatchableOp(PatchType, MBB);
+    return;
+  }
+
+  auto &TII = *MBB.getParent()->getSubtarget().getInstrInfo();
+  BuildMI(MBB, MBB.begin(), MBB.begin()->getDebugLoc(),
+          TII.get(X86::MOV32rr_REV), X86::EDI)
+      .addReg(X86::EDI)
+      .setMIFlag(MachineInstr::FrameSetup);
+}
Index: test/CodeGen/X86/ms-hotpatch-attr.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/ms-hotpatch-attr.ll
@@ -0,0 +1,27 @@
+; RUN: llc < %s -march=x86 -filetype=asm | FileCheck -check-prefix=CHECK-32 %s
+; RUN: llc < %s -march=x86-64 -filetype=asm | FileCheck -check-prefix=CHECK-64 %s
+; RUN: llc < %s -mtriple=i386-windows-msvc -filetype=asm | FileCheck -check-prefix=MSVC-32 %s
+; RUN: llc < %s -mtriple=x86_64-windows-msvc -filetype=asm | FileCheck -check-prefix=MSVC-64 %s
+
+; CHECK-32: .space 64,204
+; CHECK-32: .p2align 4, 0x90
+; CHECK-32-LABEL: foo:
+; CHECK-32: movl %edi, %edi
+; CHECK-32-NEXT: pushl %ebp
+; CHECK-32-NEXT: movl %esp, %ebp
+; CHECK-64: .space 128,204
+; CHECK-64: .p2align 4, 0x90
+; CHECK-64-LABEL: foo:
+; CHECK-64: xchgw %ax, %ax
+; MSVC-32-NOT: .space 64,204
+; MSVC-32-LABEL: _foo:
+; MSVC-32: movl %edi, %edi
+; MSVC-32-NEXT: pushl %ebp
+; MSVC-32-NEXT: movl %esp, %ebp
+; MSVC-64-NOT: .space 128,204
+; MSVC-64-LABEL: foo:
+; MSVC-64: xchgw %ax, %ax
+define void @foo() nounwind "patchable-function"="ms-hotpatch" {
+entry:
+  ret void
+}