From: whitequark Date: Thu, 22 Jun 2017 23:22:36 +0000 (+0000) Subject: Define behavior of "stack-probe-size" attribute when inlining. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e4b1890fdaff0aff7b8f4820d739d837c5f28ac5;p=llvm Define behavior of "stack-probe-size" attribute when inlining. Also document the attribute, since "probe-stack" already is. Reviewed By: majnemer Differential Revision: https://reviews.llvm.org/D34528 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306069 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LangRef.rst b/docs/LangRef.rst index ef8178efa3b..2a0812ab930 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -1511,6 +1511,21 @@ example: On an argument, this attribute indicates that the function does not write through this pointer argument, even though it may write to the memory that the pointer points to. +``"stack-probe-size"`` + This attribute controls the behavior of stack probes: either + the ``"probe-stack"`` attribute, or ABI-required stack probes, if any. + It defines the size of the guard region. It ensures that if the function + may use more stack space than the size of the guard region, stack probing + sequence will be emitted. It takes one required integer value, which + is 4096 by default. + + If a function that has a ``"stack-probe-size"`` attribute is inlined into + a function with another ``"stack-probe-size"`` attribute, the resulting + function has the ``"stack-probe-size"`` attribute that has the lower + numeric value. If a function that has a ``"stack-probe-size"`` attribute is + inlined into a function that has no ``"stack-probe-size"`` attribute + at all, the resulting function has the ``"stack-probe-size"`` attribute + of the callee. ``writeonly`` On a function, this attribute indicates that the function may write to but does not read from memory. diff --git a/include/llvm/IR/Attributes.td b/include/llvm/IR/Attributes.td index 4ca595d9773..616387816bf 100644 --- a/include/llvm/IR/Attributes.td +++ b/include/llvm/IR/Attributes.td @@ -215,3 +215,4 @@ def : MergeRule<"setOR">; def : MergeRule<"setOR">; def : MergeRule<"adjustCallerSSPLevel">; def : MergeRule<"adjustCallerStackProbes">; +def : MergeRule<"adjustCallerStackProbeSize">; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index ba2ec93ac24..8f2e641d64b 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -1641,8 +1641,34 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { /// \brief If the inlined function required stack probes, then ensure that /// the calling function has those too. static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { - if (!Caller.hasFnAttribute("probe-stack") && Callee.hasFnAttribute("probe-stack")) - Caller.addFnAttr("probe-stack", Callee.getFnAttribute("probe-stack").getValueAsString()); + if (!Caller.hasFnAttribute("probe-stack") && + Callee.hasFnAttribute("probe-stack")) { + Caller.addFnAttr(Callee.getFnAttribute("probe-stack")); + } +} + +/// \brief If the inlined function defines the size of guard region +/// on the stack, then ensure that the calling function defines a guard region +/// that is no larger. +static void +adjustCallerStackProbeSize(Function &Caller, const Function &Callee) { + if (Callee.hasFnAttribute("stack-probe-size")) { + uint64_t CalleeStackProbeSize; + Callee.getFnAttribute("stack-probe-size") + .getValueAsString() + .getAsInteger(0, CalleeStackProbeSize); + if (Caller.hasFnAttribute("stack-probe-size")) { + uint64_t CallerStackProbeSize; + Caller.getFnAttribute("stack-probe-size") + .getValueAsString() + .getAsInteger(0, CallerStackProbeSize); + if (CallerStackProbeSize > CalleeStackProbeSize) { + Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); + } + } else { + Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); + } + } } #define GET_ATTR_COMPAT_FUNC diff --git a/test/Transforms/Inline/inline-stack-probe-size.ll b/test/Transforms/Inline/inline-stack-probe-size.ll new file mode 100644 index 00000000000..d24da462d2e --- /dev/null +++ b/test/Transforms/Inline/inline-stack-probe-size.ll @@ -0,0 +1,29 @@ +; RUN: opt %s -inline -S | FileCheck %s + +define internal void @innerSmall() "stack-probe-size"="4096" { + ret void +} + +define internal void @innerLarge() "stack-probe-size"="8192" { + ret void +} + +define void @outerNoAttribute() { + call void @innerSmall() + ret void +} + +define void @outerConflictingAttributeSmall() "stack-probe-size"="4096" { + call void @innerLarge() + ret void +} + +define void @outerConflictingAttributeLarge() "stack-probe-size"="8192" { + call void @innerSmall() + ret void +} + +; CHECK: define void @outerNoAttribute() #0 +; CHECK: define void @outerConflictingAttributeSmall() #0 +; CHECK: define void @outerConflictingAttributeLarge() #0 +; CHECK: attributes #0 = { "stack-probe-size"="4096" }