diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp
index 545248ac100d40b29e71c6546e010839b4b005dc..667beffba0ea0f2030cc15bc07501d1c481f4b1d 100644
--- a/lib/Target/X86/X86FrameLowering.cpp
+++ b/lib/Target/X86/X86FrameLowering.cpp
@@ -68,7 +68,7 @@ X86FrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const {
 // needsFrameIndexResolution - Do we need to perform FI resolution for
 // this function. Normally, this is required only when the function
 // has any stack objects. However, FI resolution actually has another job,
-// not apparent from the title - it resolves callframesetup/destroy 
+// not apparent from the title - it resolves callframesetup/destroy
 // that were not simplified earlier.
 // So, this is required for x86 functions that have push sequences even
 // when there are no stack objects.
@@ -78,6 +78,11 @@ X86FrameLowering::needsFrameIndexResolution(const MachineFunction &MF) const {
          MF.getInfo<X86MachineFunctionInfo>()->getHasPushSequences();
 }
 
+static
+bool hasStackSwitch(const MachineFunction &MF) {
+    return MF.getFunction().hasFnAttribute("stackswitch-sp-symbol");
+}
+
 /// hasFP - Return true if the specified function should have a dedicated frame
 /// pointer register.  This is true if the function has variable sized allocas
 /// or if frame pointer elimination is disabled.
@@ -85,6 +90,7 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
   return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
           TRI->needsStackRealignment(MF) ||
+          hasStackSwitch(MF) ||
           MFI.hasVarSizedObjects() ||
           MFI.isFrameAddressTaken() || MFI.hasOpaqueSPAdjustment() ||
           MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() ||
@@ -603,7 +609,7 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF,
   int64_t RCXShadowSlot = 0;
   int64_t RDXShadowSlot = 0;
 
-  // If inlining in the prolog, save RCX and RDX.     
+  // If inlining in the prolog, save RCX and RDX.
   // Future optimization: don't save or restore if not live in.
   if (InProlog) {
     // Compute the offsets. We need to account for things already
@@ -1179,6 +1185,18 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
     }
   }
 
+  // Switch stack. TODO: more doc
+  if (hasStackSwitch(MF)) {
+      StringRef stack_symbol = Fn.getFnAttribute("stackswitch-sp-symbol").getValueAsString();
+      // X86AddressMode AM;
+      GlobalValue * GV = Fn.getParent()->getNamedValue(stack_symbol);
+      X86AddressMode AM;
+      AM.GV = GV;
+      addFullAddress(BuildMI(MBB, MBBI, DL,
+                             TII.get(Is64Bit ? X86::MOV64rm : X86::MOV32rm), StackPtr),
+                     AM);
+  }
+
   // Realign stack after we pushed callee-saved registers (so that we'll be
   // able to calculate their offsets from the frame pointer).
   // Don't do this for Win64, it needs to realign the stack after the prologue.
@@ -1621,9 +1639,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
   // slot before popping them off! Same applies for the case, when stack was
   // realigned. Don't do this if this was a funclet epilogue, since the funclets
   // will not do realignment or dynamic stack allocation.
-  if ((TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) &&
+  if ((TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || hasStackSwitch(MF)) &&
       !IsFunclet) {
-    if (TRI->needsStackRealignment(MF))
+    if (TRI->needsStackRealignment(MF) || hasStackSwitch(MF))
       MBBI = FirstCSPop;
     unsigned SEHFrameOffset = calculateSetFPREG(SEHStackAllocAmt);
     uint64_t LEAAmount =
@@ -2642,7 +2660,7 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB,
     Regs[FoundRegs++] = Regs[0];
 
   for (int i = 0; i < NumPops; ++i)
-    BuildMI(MBB, MBBI, DL, 
+    BuildMI(MBB, MBBI, DL,
             TII.get(STI.is64Bit() ? X86::POP64r : X86::POP32r), Regs[i]);
 
   return true;
@@ -2923,7 +2941,7 @@ struct X86FrameSortingComparator {
     // in general. Something to keep in mind, though.
     if (DensityAScaled == DensityBScaled)
       return A.ObjectAlignment < B.ObjectAlignment;
-    
+
     return DensityAScaled < DensityBScaled;
   }
 };
@@ -2959,7 +2977,7 @@ void X86FrameLowering::orderFrameObjects(
     if (ObjectSize == 0)
       // Variable size. Just use 4.
       SortingObjects[Obj].ObjectSize = 4;
-    else      
+    else
       SortingObjects[Obj].ObjectSize = ObjectSize;
   }
 
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index f979cc51da4f3c8c1c5a052d9d03a374aa87d8eb..690e51aa4fcd99bda4e3728f637a9ddd0233ead9 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -602,6 +602,9 @@ static bool CantUseSP(const MachineFrameInfo &MFI) {
 bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
    const MachineFrameInfo &MFI = MF.getFrameInfo();
 
+   if (MF.getFunction().hasFnAttribute("stackswitch-sp-symbol"))
+     return true;
+
    if (!EnableBasePointer)
      return false;
 
diff --git a/test/CodeGen/X86/stackswitch-symbol-basic.ll b/test/CodeGen/X86/stackswitch-symbol-basic.ll
new file mode 100644
index 0000000000000000000000000000000000000000..dc618303cbdafa229f083f28f53a6399a66278b9
--- /dev/null
+++ b/test/CodeGen/X86/stackswitch-symbol-basic.ll
@@ -0,0 +1,34 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu  \
+; RUN:              | FileCheck %s 
+
+
+@DOSEK_BasicTaskStack = external global i8*, align 8
+@.str = private unnamed_addr constant [3 x i8] c"%s\00", align 1
+@.str1 = private unnamed_addr constant [10 x i8] c"Success!\0A\00", align 1
+
+; Function Attrs: nounwind
+; Function Attrs: noinline nounwind uwtable
+define i32 @foo(i8*) #0 {
+; CHECK: movl %esp, %ebp
+; CHECK: movl DOSEK_BasicTaskStack, %esp
+; CHECK: movl %esp, %esi
+  %2 = alloca i8*, align 8
+  store i8* %0, i8** %2, align 8
+  %3 = load i8*, i8** %2, align 8
+  %4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8* %3)
+  ret i32 %4
+; CHECK: leal -{{[0-9]+}}(%ebp), %esp
+; CHECK: popl %esi
+}
+
+declare i32 @printf(i8*, ...) 
+
+; Function Attrs: nounwind
+define i32 @main() {
+  %1 = alloca i32, align 4
+  store i32 0, i32* %1, align 4
+  %2 = call i32 @foo(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str1, i32 0, i32 0))
+  ret i32 %2
+}
+
+attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack" }
diff --git a/test/CodeGen/X86/stackswitch-symbol-dynamic.ll b/test/CodeGen/X86/stackswitch-symbol-dynamic.ll
new file mode 100644
index 0000000000000000000000000000000000000000..dcf4adb74638f3ffe40062f9b9262fd863669c36
--- /dev/null
+++ b/test/CodeGen/X86/stackswitch-symbol-dynamic.ll
@@ -0,0 +1,26 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu  \
+; RUN:              | FileCheck %s 
+
+@DOSEK_BasicTaskStack = external global i8*, align 8
+
+; Function Attrs: nounwind
+define void @mad(i32 %length) #0 {
+; CHECK: movl %esp, %ebp
+; CHECK: movl DOSEK_BasicTaskStack, %esp
+; CHECK: movl %esp, %esi
+  %m = alloca i32, i32 %length
+  ret void
+; CHECK: leal -{{[0-9]+}}(%ebp), %esp
+; CHECK: popl %esi
+}
+
+; Function Attrs: nounwind
+define i32 @main(i32 %argc, i8** %argv)  {
+; CHECK-NOT: DOSEK_BasicTaskStack
+  call void @mad(i32 32750)
+  ret i32 0
+}
+
+
+attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack"}
+
diff --git a/test/CodeGen/X86/stackswitch-symbol-recursion.ll b/test/CodeGen/X86/stackswitch-symbol-recursion.ll
new file mode 100644
index 0000000000000000000000000000000000000000..55f3229b5cabb7380cf64b1c57a8258f0428950a
--- /dev/null
+++ b/test/CodeGen/X86/stackswitch-symbol-recursion.ll
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu  \
+; RUN:              | FileCheck %s 
+
+@DOSEK_BasicTaskStack = external global i8*, align 8
+
+define i32 @bar(i32 %start) {
+; CHECK-NOT: DOSEK_BasicTaskStack
+  %1 = call i32 @bar(i32 %start)
+  ret i32 %1
+
+}
+
+; Function Attrs: nounwind
+define i32 @foo(i32 %start) #0 {
+; CHECK: movl %esp, %ebp
+; CHECK: movl DOSEK_BasicTaskStack, %esp
+  %1 = call i32 @bar(i32 2)
+  ret i32 %1
+; CHECK: leal -{{[0-9]+}}(%ebp), %esp
+}
+
+; Function Attrs: nounwind
+define i32 @main(i32 %argc, i8** %argv)  {
+; CHECK-NOT: DOSEK_BasicTaskStack
+  %1 = call i32 @foo(i32 -10000)
+  ret i32 0
+}
+
+
+attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack" }