Skip to content

Commit d1a1d7a

Browse files
[llvm][AArch64] Do not inline a function with different signing scheme. (#80642) (#82743)
f 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.
1 parent 9274829 commit d1a1d7a

File tree

4 files changed

+135
-8
lines changed

4 files changed

+135
-8
lines changed

llvm/include/llvm/IR/Attributes.td

+21-7
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,26 @@ def UseSampleProfile : StrBoolAttr<"use-sample-profile">;
339339
def DenormalFPMath : ComplexStrAttr<"denormal-fp-math", [FnAttr]>;
340340
def DenormalFPMathF32 : ComplexStrAttr<"denormal-fp-math-f32", [FnAttr]>;
341341

342+
// Attribute compatiblity rules are generated to check the attribute of the
343+
// caller and callee and decide whether inlining should be allowed. CompatRule
344+
// and child classes are used for the rule generation. CompatRule takes only a
345+
// compare function which could be templated with the attribute type.
346+
// CompatRuleStrAttr takes the compare function and the string attribute for
347+
// checking compatibility for inline substitution.
342348
class CompatRule<string F> {
343-
// The name of the function called to check the attribute of the caller and
344-
// callee and decide whether inlining should be allowed. The function's
345-
// signature must match "bool(const Function&, const Function &)", where the
346-
// first parameter is the reference to the caller and the second parameter is
347-
// the reference to the callee. It must return false if the attributes of the
348-
// caller and callee are incompatible, and true otherwise.
349+
// The function's signature must match "bool(const Function&, const
350+
// Function&)", where the first parameter is the reference to the caller and
351+
// the second parameter is the reference to the callee. It must return false
352+
// if the attributes of the caller and callee are incompatible, and true
353+
// otherwise.
349354
string CompatFunc = F;
355+
string AttrName = "";
356+
}
357+
358+
class CompatRuleStrAttr<string F, string Attr> : CompatRule<F> {
359+
// The checker function is extended with an third argument as the function
360+
// attribute string "bool(const Function&, const Function&, const StringRef&)".
361+
string AttrName = Attr;
350362
}
351363

352364
def : CompatRule<"isEqual<SanitizeAddressAttr>">;
@@ -359,7 +371,9 @@ def : CompatRule<"isEqual<ShadowCallStackAttr>">;
359371
def : CompatRule<"isEqual<UseSampleProfileAttr>">;
360372
def : CompatRule<"isEqual<NoProfileAttr>">;
361373
def : CompatRule<"checkDenormMode">;
362-
374+
def : CompatRuleStrAttr<"isEqual", "sign-return-address">;
375+
def : CompatRuleStrAttr<"isEqual", "sign-return-address-key">;
376+
def : CompatRuleStrAttr<"isEqual", "branch-protection-pauth-lr">;
363377

364378
class MergeRule<string F> {
365379
// The name of the function called to merge the attributes of the caller and

llvm/lib/IR/Attributes.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,11 @@ static bool isEqual(const Function &Caller, const Function &Callee) {
20452045
Callee.getFnAttribute(AttrClass::getKind());
20462046
}
20472047

2048+
static bool isEqual(const Function &Caller, const Function &Callee,
2049+
const StringRef &AttrName) {
2050+
return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2051+
}
2052+
20482053
/// Compute the logical AND of the attributes of the caller and the
20492054
/// callee.
20502055
///
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
; Check the inliner doesn't inline a function with different sign return address schemes.
2+
; RUN: opt < %s -passes=inline -S | FileCheck %s
3+
4+
define internal void @foo_all() #0 {
5+
ret void
6+
}
7+
8+
define internal void @foo_nonleaf() #1 {
9+
ret void
10+
}
11+
12+
define internal void @foo_none() #2 {
13+
ret void
14+
}
15+
16+
define internal void @foo_lr() #3 {
17+
ret void
18+
}
19+
20+
define internal void @foo_bkey() #4 {
21+
ret void
22+
}
23+
24+
define dso_local void @bar_all() #0 {
25+
; CHECK-LABEL: bar_all
26+
; CHECK-NOT: call void @foo_all()
27+
; CHECK-NEXT: call void @foo_nonleaf()
28+
; CHECK-NEXT: call void @foo_none()
29+
; CHECK-NEXT: call void @foo_lr()
30+
; CHECK-NEXT: call void @foo_bkey()
31+
call void @foo_all()
32+
call void @foo_nonleaf()
33+
call void @foo_none()
34+
call void @foo_lr()
35+
call void @foo_bkey()
36+
ret void
37+
}
38+
39+
define dso_local void @bar_nonleaf() #1 {
40+
; CHECK-LABEL: bar_nonleaf
41+
; CHECK-NEXT: call void @foo_all()
42+
; CHECK-NOT: call void @foo_nonleaf()
43+
; CHECK-NEXT: call void @foo_none()
44+
; CHECK-NEXT: call void @foo_lr()
45+
; CHECK-NEXT: call void @foo_bkey()
46+
call void @foo_all()
47+
call void @foo_nonleaf()
48+
call void @foo_none()
49+
call void @foo_lr()
50+
call void @foo_bkey()
51+
ret void
52+
}
53+
54+
define dso_local void @bar_none() #2 {
55+
; CHECK-LABEL: bar_none
56+
; CHECK-NEXT: call void @foo_all()
57+
; CHECK-NEXT: call void @foo_nonleaf()
58+
; CHECK-NOT: call void @foo_none()
59+
; CHECK-NEXT: call void @foo_lr()
60+
; CHECK-NEXT: call void @foo_bkey()
61+
call void @foo_all()
62+
call void @foo_nonleaf()
63+
call void @foo_none()
64+
call void @foo_lr()
65+
call void @foo_bkey()
66+
ret void
67+
}
68+
69+
define dso_local void @bar_lr() #3 {
70+
; CHECK-LABEL: bar_lr
71+
; CHECK-NEXT: call void @foo_all()
72+
; CHECK-NEXT: call void @foo_nonleaf()
73+
; CHECK-NEXT: call void @foo_none()
74+
; CHECK-NOT: call void @foo_lr()
75+
; CHECK-NEXT: call void @foo_bkey()
76+
call void @foo_all()
77+
call void @foo_nonleaf()
78+
call void @foo_none()
79+
call void @foo_lr()
80+
call void @foo_bkey()
81+
ret void
82+
}
83+
84+
define dso_local void @bar_bkey() #4 {
85+
; CHECK-LABEL: bar_bkey
86+
; CHECK-NEXT: call void @foo_all()
87+
; CHECK-NEXT: call void @foo_nonleaf()
88+
; CHECK-NEXT: call void @foo_none()
89+
; CHECK-NEXT: call void @foo_lr()
90+
; CHECK-NOT: call void @foo_bkey()
91+
call void @foo_all()
92+
call void @foo_nonleaf()
93+
call void @foo_none()
94+
call void @foo_lr()
95+
call void @foo_bkey()
96+
ret void
97+
}
98+
99+
100+
attributes #0 = { "branch-protection-pauth-lr"="false" "sign-return-address"="all" }
101+
attributes #1 = { "branch-protection-pauth-lr"="false" "sign-return-address"="non-leaf" }
102+
attributes #2 = { "branch-protection-pauth-lr"="false" "sign-return-address"="none" }
103+
attributes #3 = { "branch-protection-pauth-lr"="true" "sign-return-address"="non-leaf" }
104+
attributes #4 = { "branch-protection-pauth-lr"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" }

llvm/utils/TableGen/Attributes.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
8787

8888
for (auto *Rule : CompatRules) {
8989
StringRef FuncName = Rule->getValueAsString("CompatFunc");
90-
OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
90+
OS << " Ret &= " << FuncName << "(Caller, Callee";
91+
StringRef AttrName = Rule->getValueAsString("AttrName");
92+
if (!AttrName.empty())
93+
OS << ", \"" << AttrName << "\"";
94+
OS << ");\n";
9195
}
9296

9397
OS << "\n";

0 commit comments

Comments
 (0)