[llvm] [llvm][AArch64] Do not inline a function with different signing scheme. (PR #80642)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 14:12:13 PST 2024
https://github.com/DanielKristofKiss updated https://github.com/llvm/llvm-project/pull/80642
>From 823a9391ad8f04d1fe9cbf6d6c3f380efdcc60a0 Mon Sep 17 00:00:00 2001
From: Daniel Kiss <daniel.kiss at arm.com>
Date: Wed, 24 Jan 2024 16:05:07 +0100
Subject: [PATCH] [llvm][Arm][AArch64] Do not inline a function with different
signing scheme.
If the signing scheme is different that maybe the functions assumes different behaviours and dangerous to inline them without analysing them.
This should be a rare case.
---
llvm/include/llvm/IR/Attributes.td | 14 ++-
llvm/lib/IR/Attributes.cpp | 12 ++
llvm/lib/Transforms/Utils/InlineFunction.cpp | 7 --
.../Inline/inline-sign-return-address.ll | 104 ++++++++++++++++++
llvm/utils/TableGen/Attributes.cpp | 7 +-
5 files changed, 134 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/Transforms/Inline/inline-sign-return-address.ll
diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index 864f87f3383891..f04261111d6462 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -342,11 +342,18 @@ def DenormalFPMathF32 : ComplexStrAttr<"denormal-fp-math-f32", [FnAttr]>;
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
+ // 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 CompatRuleAttr<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>">;
@@ -359,7 +366,10 @@ def : CompatRule<"isEqual<ShadowCallStackAttr>">;
def : CompatRule<"isEqual<UseSampleProfileAttr>">;
def : CompatRule<"isEqual<NoProfileAttr>">;
def : CompatRule<"checkDenormMode">;
-
+def : CompatRule<"checkStrictFP">;
+def : CompatRuleAttr<"isEqual", "sign-return-address">;
+def : CompatRuleAttr<"isEqual", "sign-return-address-key">;
+def : CompatRuleAttr<"isEqual", "branch-protection-pauth-lr">;
class MergeRule<string F> {
// The name of the function called to merge the attributes of the caller and
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index fd5160209506f2..d5a294a09b5b62 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2039,12 +2039,24 @@ static bool checkDenormMode(const Function &Caller, const Function &Callee) {
return false;
}
+static bool checkStrictFP(const Function &Caller, const Function &Callee) {
+ // Do not inline strictfp function into non-strictfp one. It would require
+ // conversion of all FP operations in host function to constrained intrinsics.
+ return !(Callee.getAttributes().hasFnAttr(Attribute::StrictFP) &&
+ !Caller.getAttributes().hasFnAttr(Attribute::StrictFP));
+}
+
template<typename AttrClass>
static bool isEqual(const Function &Caller, const Function &Callee) {
return Caller.getFnAttribute(AttrClass::getKind()) ==
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.
///
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index d4d4bf5ebdf36e..6ea68497d7a6ed 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2103,13 +2103,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
BasicBlock *OrigBB = CB.getParent();
Function *Caller = OrigBB->getParent();
- // Do not inline strictfp function into non-strictfp one. It would require
- // conversion of all FP operations in host function to constrained intrinsics.
- if (CalledFunc->getAttributes().hasFnAttr(Attribute::StrictFP) &&
- !Caller->getAttributes().hasFnAttr(Attribute::StrictFP)) {
- return InlineResult::failure("incompatible strictfp attributes");
- }
-
// GC poses two hazards to inlining, which only occur when the callee has GC:
// 1. If the caller has no GC, then the callee's GC must be propagated to the
// caller.
diff --git a/llvm/test/Transforms/Inline/inline-sign-return-address.ll b/llvm/test/Transforms/Inline/inline-sign-return-address.ll
new file mode 100644
index 00000000000000..c4d85fa671a4f6
--- /dev/null
+++ b/llvm/test/Transforms/Inline/inline-sign-return-address.ll
@@ -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" }
\ No newline at end of file
diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp
index 474042a3e9a331..c310c03181fa82 100644
--- a/llvm/utils/TableGen/Attributes.cpp
+++ b/llvm/utils/TableGen/Attributes.cpp
@@ -87,7 +87,12 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
for (auto *Rule : CompatRules) {
StringRef FuncName = Rule->getValueAsString("CompatFunc");
- OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
+ StringRef AttrName = Rule->getValueAsString("AttrName");
+ if (AttrName.empty())
+ OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
+ else
+ OS << " Ret &= " << FuncName << "(Caller, Callee, \"" << AttrName
+ << "\");\n";
}
OS << "\n";
More information about the llvm-commits
mailing list