Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm][AArch64] Do not inline a function with different signing scheme. #80642

Merged
merged 3 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions llvm/include/llvm/IR/Attributes.td
Original file line number Diff line number Diff line change
Expand Up @@ -339,14 +339,26 @@ def UseSampleProfile : StrBoolAttr<"use-sample-profile">;
def DenormalFPMath : ComplexStrAttr<"denormal-fp-math", [FnAttr]>;
def DenormalFPMathF32 : ComplexStrAttr<"denormal-fp-math-f32", [FnAttr]>;

// Attiribute compatiblity rules are generated to check the attribute of the
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
// caller and callee and decide whether inlining should be allowed. CompatRule
// and child classes are used for the rule generation. CompatRule takes only a
// compare function which could be templated with the attribute type.
// CompatRuleStrAttr takes the compare function and the string for checking the
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
// string attributes.
nickdesaulniers marked this conversation as resolved.
Show resolved Hide resolved
class CompatRule<string F> {
// The name of the function called to check the attribute of the caller and
// callee and decide whether inlining should be allowed. The function's
// signature must match "bool(const Function&, const Function &)", where the
// first parameter is the reference to the caller and the second parameter is
// the reference to the callee. It must return false if the attributes of the
// caller and callee are incompatible, and true otherwise.
// The function's signature must match "bool(const Function&, const
// Function&)", where the first parameter is the reference to the caller and
// the second parameter is the reference to the callee. It must return false
// if the attributes of the caller and callee are incompatible, and true
// otherwise.
string CompatFunc = F;
string AttrName = "";
}

class CompatRuleStrAttr<string F, string Attr> : CompatRule<F> {
// The checker function is extended with an third argument as the function
// attribute string "bool(const Function&, const Function&, const StringRef&)".
string AttrName = Attr;
}

def : CompatRule<"isEqual<SanitizeAddressAttr>">;
Expand All @@ -359,7 +371,9 @@ def : CompatRule<"isEqual<ShadowCallStackAttr>">;
def : CompatRule<"isEqual<UseSampleProfileAttr>">;
def : CompatRule<"isEqual<NoProfileAttr>">;
def : CompatRule<"checkDenormMode">;

def : CompatRuleStrAttr<"isEqual", "sign-return-address">;
def : CompatRuleStrAttr<"isEqual", "sign-return-address-key">;
def : CompatRuleStrAttr<"isEqual", "branch-protection-pauth-lr">;

class MergeRule<string F> {
// The name of the function called to merge the attributes of the caller and
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2045,6 +2045,11 @@ static bool isEqual(const Function &Caller, const Function &Callee) {
Callee.getFnAttribute(AttrClass::getKind());
}

static bool isEqual(const Function &Caller, const Function &Callee,
const StringRef &AttrName) {
return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
}

/// Compute the logical AND of the attributes of the caller and the
/// callee.
///
Expand Down
104 changes: 104 additions & 0 deletions llvm/test/Transforms/Inline/inline-sign-return-address.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
; Check the inliner doesn't inline a function with different sign return address schemes.
; RUN: opt < %s -passes=inline -S | FileCheck %s

define internal void @foo_all() #0 {
ret void
}

define internal void @foo_nonleaf() #1 {
ret void
}

define internal void @foo_none() #2 {
ret void
}

define internal void @foo_lr() #3 {
ret void
}

define internal void @foo_bkey() #4 {
ret void
}

define dso_local void @bar_all() #0 {
; CHECK-LABEL: bar_all
; CHECK-NOT: call void @foo_all()
; CHECK-NEXT: call void @foo_nonleaf()
; CHECK-NEXT: call void @foo_none()
; CHECK-NEXT: call void @foo_lr()
; CHECK-NEXT: call void @foo_bkey()
call void @foo_all()
call void @foo_nonleaf()
call void @foo_none()
call void @foo_lr()
call void @foo_bkey()
ret void
}

define dso_local void @bar_nonleaf() #1 {
; CHECK-LABEL: bar_nonleaf
; CHECK-NEXT: call void @foo_all()
; CHECK-NOT: call void @foo_nonleaf()
; CHECK-NEXT: call void @foo_none()
; CHECK-NEXT: call void @foo_lr()
; CHECK-NEXT: call void @foo_bkey()
call void @foo_all()
call void @foo_nonleaf()
call void @foo_none()
call void @foo_lr()
call void @foo_bkey()
ret void
}

define dso_local void @bar_none() #2 {
; CHECK-LABEL: bar_none
; CHECK-NEXT: call void @foo_all()
; CHECK-NEXT: call void @foo_nonleaf()
; CHECK-NOT: call void @foo_none()
; CHECK-NEXT: call void @foo_lr()
; CHECK-NEXT: call void @foo_bkey()
call void @foo_all()
call void @foo_nonleaf()
call void @foo_none()
call void @foo_lr()
call void @foo_bkey()
ret void
}

define dso_local void @bar_lr() #3 {
; CHECK-LABEL: bar_lr
; CHECK-NEXT: call void @foo_all()
; CHECK-NEXT: call void @foo_nonleaf()
; CHECK-NEXT: call void @foo_none()
; CHECK-NOT: call void @foo_lr()
; CHECK-NEXT: call void @foo_bkey()
call void @foo_all()
call void @foo_nonleaf()
call void @foo_none()
call void @foo_lr()
call void @foo_bkey()
ret void
}

define dso_local void @bar_bkey() #4 {
; CHECK-LABEL: bar_bkey
; CHECK-NEXT: call void @foo_all()
; CHECK-NEXT: call void @foo_nonleaf()
; CHECK-NEXT: call void @foo_none()
; CHECK-NEXT: call void @foo_lr()
; CHECK-NOT: call void @foo_bkey()
call void @foo_all()
call void @foo_nonleaf()
call void @foo_none()
call void @foo_lr()
call void @foo_bkey()
ret void
}


attributes #0 = { "branch-protection-pauth-lr"="false" "sign-return-address"="all" }
attributes #1 = { "branch-protection-pauth-lr"="false" "sign-return-address"="non-leaf" }
attributes #2 = { "branch-protection-pauth-lr"="false" "sign-return-address"="none" }
attributes #3 = { "branch-protection-pauth-lr"="true" "sign-return-address"="non-leaf" }
attributes #4 = { "branch-protection-pauth-lr"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" }
6 changes: 5 additions & 1 deletion llvm/utils/TableGen/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {

for (auto *Rule : CompatRules) {
StringRef FuncName = Rule->getValueAsString("CompatFunc");
OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
OS << " Ret &= " << FuncName << "(Caller, Callee";
StringRef AttrName = Rule->getValueAsString("AttrName");
if (!AttrName.empty())
OS << ", \"" << AttrName << "\"";
OS << ");\n";
}

OS << "\n";
Expand Down
Loading