From 60812c05e748e183becba2cfe945fb2621ea1c9f Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 7 Jan 2015 18:14:07 +0000 Subject: [PATCH] X86: Allow the stack probe size to be configurable per function LLVM emits stack probes on Windows targets to ensure that the stack is correctly accessed. However, the amount of stack allocated before emitting such a probe is hardcoded to 4096. It is desirable to have this be configurable so that a function might opt-out of stack probes. Our level of granularity is at the function level instead of, say, the module level to permit proper generation of code after LTO. Patch by Andrew H! N.B. The inliner needs to be updated to properly consider what happens after inlining a function with a specific stack-probe-size into another function with a different stack-probe-size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225360 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FrameLowering.cpp | 12 +++-- test/CodeGen/X86/stack-probe-size.ll | 78 ++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/X86/stack-probe-size.ll diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 8779acc6a08..16aab16d63e 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -528,6 +528,14 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { bool UseStackProbe = (STI.isOSWindows() && !STI.isTargetMachO()); + // The default stack probe size is 4096 if the function has no stackprobesize + // attribute. + unsigned StackProbeSize = 4096; + if (Fn->hasFnAttribute("stack-probe-size")) + Fn->getFnAttribute("stack-probe-size") + .getValueAsString() + .getAsInteger(0, StackProbeSize); + // If this is x86-64 and the Red Zone is not disabled, if we are a leaf // function, and use up to 128 bytes of stack space, don't have a frame // pointer, calls, or dynamic alloca then we do not need to adjust the @@ -705,8 +713,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { // Adjust stack pointer: ESP -= numbytes. - static const size_t PageSize = 4096; - // Windows and cygwin/mingw require a prologue helper routine when allocating // more than 4K bytes on the stack. Windows uses __chkstk and cygwin/mingw // uses __alloca. __alloca and the 32-bit version of __chkstk will probe the @@ -715,7 +721,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF) const { // responsible for adjusting the stack pointer. Touching the stack at 4K // increments is necessary to ensure that the guard pages used by the OS // virtual memory manager are allocated in correct sequence. - if (NumBytes >= PageSize && UseStackProbe) { + if (NumBytes >= StackProbeSize && UseStackProbe) { const char *StackProbeSymbol; unsigned CallOp; diff --git a/test/CodeGen/X86/stack-probe-size.ll b/test/CodeGen/X86/stack-probe-size.ll new file mode 100644 index 00000000000..21482c3abde --- /dev/null +++ b/test/CodeGen/X86/stack-probe-size.ll @@ -0,0 +1,78 @@ +; This test is attempting to detect that the compiler correctly generates stack +; probe calls when the size of the local variables exceeds the specified stack +; probe size. +; +; Testing the default value of 4096 bytes makes sense, because the default +; stack probe size equals the page size (4096 bytes for all x86 targets), and +; this is unlikely to change in the future. +; +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" +target triple = "i686-pc-windows-msvc" + +define i32 @test1() "stack-probe-size"="0" { + %buffer = alloca [4095 x i8] + + ret i32 0 + +; CHECK-LABEL: _test1: +; CHECK-NOT: subl $4095, %esp +; CHECK: movl $4095, %eax +; CHECK: calll __chkstk +} + +define i32 @test2() { + %buffer = alloca [4095 x i8] + + ret i32 0 + +; CHECK-LABEL: _test2: +; CHECK-NOT: movl $4095, %eax +; CHECK: subl $4095, %esp +; CHECK-NOT: calll __chkstk +} + +define i32 @test3() "stack-probe-size"="8192" { + %buffer = alloca [4095 x i8] + + ret i32 0 + +; CHECK-LABEL: _test3: +; CHECK-NOT: movl $4095, %eax +; CHECK: subl $4095, %esp +; CHECK-NOT: calll __chkstk +} + +define i32 @test4() "stack-probe-size"="0" { + %buffer = alloca [4096 x i8] + + ret i32 0 + +; CHECK-LABEL: _test4: +; CHECK-NOT: subl $4096, %esp +; CHECK: movl $4096, %eax +; CHECK: calll __chkstk +} + +define i32 @test5() { + %buffer = alloca [4096 x i8] + + ret i32 0 + +; CHECK-LABEL: _test5: +; CHECK-NOT: subl $4096, %esp +; CHECK: movl $4096, %eax +; CHECK: calll __chkstk +} + +define i32 @test6() "stack-probe-size"="8192" { + %buffer = alloca [4096 x i8] + + ret i32 0 + +; CGECK-LABEL: _test6: +; CGECK-NOT: movl $4096, %eax +; CGECK: subl $4096, %esp +; CGECK-NOT: calll __chkstk +} -- 2.34.1