Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -735,18 +735,33 @@ .setMIFlag(MachineInstr::FrameSetup); } + MachineInstrBuilder MIB; + if (Is64Bit) { // Handle the 64-bit Windows ABI case where we need to call __chkstk. // Function prologue is responsible for adjusting the stack pointer. BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::RAX) .addImm(NumBytes) .setMIFlag(MachineInstr::FrameSetup); + + // R11 will be used to contain the address of __chkstk. + // R11 is a volatile register and assumed to be destroyed by the callee, + // so there is no need to save and restore it. + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::R11) + .addExternalSymbol(StackProbeSymbol); + + // Create a call to __chkstk function which address contained in R11. + MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALL64r)) + .addReg(X86::R11, RegState::Kill); } else { // Allocate NumBytes-4 bytes on stack in case of isEAXAlive. // We'll also use 4 already allocated bytes for EAX. BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) .addImm(isEAXAlive ? NumBytes - 4 : NumBytes) .setMIFlag(MachineInstr::FrameSetup); + + MIB = BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) + .addExternalSymbol(StackProbeSymbol); } BuildMI(MBB, MBBI, DL, @@ -758,7 +773,7 @@ if (Is64Bit) { // MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp - // themself. It also does not clobber %rax so we can reuse it when + // themselves. It also does not clobber %rax so we can reuse it when // adjusting %rsp. BuildMI(MBB, MBBI, DL, TII.get(X86::SUB64rr), StackPtr) .addReg(StackPtr) Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -20937,12 +20937,24 @@ // non-trivial part is impdef of ESP. if (Subtarget->isTargetWin64()) { + const char *StackProbeSymbol = + Subtarget->isTargetCygMing() ? "___chkstk" : "__chkstk"; + + // R11 will be used to contain the address of __chkstk. + // R11 is a volotiale register and assumed to be destoyed by the callee, + // so there is no need to save and restore it. + BuildMI(*BB, MI, DL, TII->get(X86::MOV64ri), X86::R11) + .addExternalSymbol(StackProbeSymbol); + + // Create a call to __chkstk function which address contained in R11. + MachineInstrBuilder MIB = BuildMI(*BB, MI, DL, TII->get(X86::CALL64r)) + .addReg(X86::R11, RegState::Kill); + if (Subtarget->isTargetCygMing()) { // ___chkstk(Mingw64): // Clobbers R10, R11, RAX and EFLAGS. // Updates RSP. - BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA)) - .addExternalSymbol("___chkstk") + MIB .addReg(X86::RAX, RegState::Implicit) .addReg(X86::RSP, RegState::Implicit) .addReg(X86::RAX, RegState::Define | RegState::Implicit) @@ -20951,8 +20963,7 @@ } else { // __chkstk(MSVCRT): does not update stack pointer. // Clobbers R10, R11 and EFLAGS. - BuildMI(*BB, MI, DL, TII->get(X86::W64ALLOCA)) - .addExternalSymbol("__chkstk") + MIB .addReg(X86::RAX, RegState::Implicit) .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); // RAX has the offset to be subtracted from RSP. Index: test/CodeGen/X86/win64_alloca_dynalloca.ll =================================================================== --- test/CodeGen/X86/win64_alloca_dynalloca.ll +++ test/CodeGen/X86/win64_alloca_dynalloca.ll @@ -15,13 +15,15 @@ ; ___chkstk_ms does not adjust %rsp. ; M64: movq %rsp, %rbp ; M64: $4096, %rax -; M64: callq ___chkstk_ms +; M64: movabsq $___chkstk_ms, %r11 +; M64: callq *%r11 ; M64: subq %rax, %rsp ; __chkstk does not adjust %rsp. ; W64: movq %rsp, %rbp ; W64: $4096, %rax -; W64: callq __chkstk +; W64: movabsq $__chkstk, %r11 +; W64: callq *%r11 ; W64: subq %rax, %rsp ; Freestanding @@ -33,13 +35,15 @@ ; M64: leaq 15(%{{.*}}), %rax ; M64: andq $-16, %rax -; M64: callq ___chkstk +; M64: movabsq $___chkstk, %r11 +; M64: callq *%r11 ; M64-NOT: %rsp ; M64: movq %rsp, %rax ; W64: leaq 15(%{{.*}}), %rax ; W64: andq $-16, %rax -; W64: callq __chkstk +; W64: movabsq $__chkstk, %r11 +; W64: callq *%r11 ; W64: subq %rax, %rsp ; W64: movq %rsp, %rax @@ -84,14 +88,16 @@ ; M64: leaq 15(%{{.*}}), %rax ; M64: andq $-16, %rax -; M64: callq ___chkstk +; M64: movabsq $___chkstk, %r11 +; M64: callq *%r11 ; M64: movq %rsp, [[R2:%r.*]] ; M64: andq $-128, [[R2]] ; M64: movq [[R2]], %rsp ; W64: leaq 15(%{{.*}}), %rax ; W64: andq $-16, %rax -; W64: callq __chkstk +; W64: movabsq $__chkstk, %r11 +; W64: callq *%r11 ; W64: subq %rax, %rsp ; W64: movq %rsp, [[R2:%r.*]] ; W64: andq $-128, [[R2]] Index: test/CodeGen/X86/win64_eh.ll =================================================================== --- test/CodeGen/X86/win64_eh.ll +++ test/CodeGen/X86/win64_eh.ll @@ -36,7 +36,8 @@ ; WIN64-LABEL: foo2: ; WIN64: .seh_proc foo2 ; WIN64: movabsq $8000, %rax -; WIN64: callq {{__chkstk|___chkstk_ms}} +; WIN64: movabsq ${{__chkstk|___chkstk_ms}}, %r11 +; WIN64: callq *%r11 ; WIN64: subq %rax, %rsp ; WIN64: .seh_stackalloc 8000 ; WIN64: .seh_endprologue Index: test/CodeGen/X86/win_chkstk.ll =================================================================== --- test/CodeGen/X86/win_chkstk.ll +++ test/CodeGen/X86/win_chkstk.ll @@ -15,9 +15,11 @@ define i32 @main4k() nounwind { entry: ; WIN_X32: calll __chkstk -; WIN_X64: callq __chkstk +; WIN_X64: movabsq $__chkstk, %r11 +; WIN_X64: callq *%r11 ; MINGW_X32: calll __alloca -; MINGW_X64: callq ___chkstk_ms +; MINGW_X64: movabsq $___chkstk_ms, %r11 +; MINGW_X64: callq *%r11 ; LINUX-NOT: call __chkstk %array4096 = alloca [4096 x i8], align 16 ; <[4096 x i8]*> [#uses=0] ret i32 0 @@ -32,11 +34,13 @@ ; WIN_X32: ret ; WIN_X64: # BB#0: -; WIN_X64-NOT: callq __chkstk +; WIN_X64-NOT: movabsq $__chkstk, %r11 +; WIN_X64-NOT: callq *%r11 ; WIN_X64: ret ; MINGW_X64: # BB#0: -; MINGW_X64-NOT: callq ___chkstk_ms +; MINGW_X64-NOT: movabsq $___chkstk_ms, %r11 +; MINGW_X64-NOT: callq *%r11 ; MINGW_X64: ret ; LINUX: # BB#0: @@ -51,9 +55,11 @@ define x86_64_win64cc i32 @main4k_win64() nounwind { entry: ; WIN_X32: calll __chkstk -; WIN_X64: callq __chkstk +; WIN_X64: movabsq $__chkstk, %r11 +; WIN_X64: callq *%r11 ; MINGW_X32: calll __alloca -; MINGW_X64: callq ___chkstk_ms +; MINGW_X64: movabsq $___chkstk_ms, %r11 +; MINGW_X64: callq *%r11 ; LINUX-NOT: call __chkstk %array4096 = alloca [4096 x i8], align 16 ; <[4096 x i8]*> [#uses=0] ret i32 0