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
This commit is contained in:
whitequark 2017-06-22 23:22:36 +00:00
parent e83d2eccef
commit e4b1890fda
4 changed files with 73 additions and 2 deletions

View File

@ -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.

View File

@ -215,3 +215,4 @@ def : MergeRule<"setOR<NoImplicitFloatAttr>">;
def : MergeRule<"setOR<NoJumpTablesAttr>">;
def : MergeRule<"adjustCallerSSPLevel">;
def : MergeRule<"adjustCallerStackProbes">;
def : MergeRule<"adjustCallerStackProbeSize">;

View File

@ -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

View File

@ -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" }