Skip to content

Commit 823a939

Browse files
[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.
1 parent 9b80ab4 commit 823a939

File tree

5 files changed

+134
-10
lines changed

5 files changed

+134
-10
lines changed

llvm/include/llvm/IR/Attributes.td

+12-2
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,18 @@ def DenormalFPMathF32 : ComplexStrAttr<"denormal-fp-math-f32", [FnAttr]>;
342342
class CompatRule<string F> {
343343
// The name of the function called to check the attribute of the caller and
344344
// callee and decide whether inlining should be allowed. The function's
345-
// signature must match "bool(const Function&, const Function &)", where the
345+
// signature must match "bool(const Function&, const Function&)", where the
346346
// first parameter is the reference to the caller and the second parameter is
347347
// the reference to the callee. It must return false if the attributes of the
348348
// caller and callee are incompatible, and true otherwise.
349349
string CompatFunc = F;
350+
string AttrName = "";
351+
}
352+
353+
class CompatRuleAttr<string F, string Attr> : CompatRule<F> {
354+
// The checker function is extended with an third argument as the function attribute string.
355+
// bool(const Function&, const Function&, const StringRef&)"
356+
string AttrName = Attr;
350357
}
351358

352359
def : CompatRule<"isEqual<SanitizeAddressAttr>">;
@@ -359,7 +366,10 @@ def : CompatRule<"isEqual<ShadowCallStackAttr>">;
359366
def : CompatRule<"isEqual<UseSampleProfileAttr>">;
360367
def : CompatRule<"isEqual<NoProfileAttr>">;
361368
def : CompatRule<"checkDenormMode">;
362-
369+
def : CompatRule<"checkStrictFP">;
370+
def : CompatRuleAttr<"isEqual", "sign-return-address">;
371+
def : CompatRuleAttr<"isEqual", "sign-return-address-key">;
372+
def : CompatRuleAttr<"isEqual", "branch-protection-pauth-lr">;
363373

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

llvm/lib/IR/Attributes.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -2039,12 +2039,24 @@ static bool checkDenormMode(const Function &Caller, const Function &Callee) {
20392039
return false;
20402040
}
20412041

2042+
static bool checkStrictFP(const Function &Caller, const Function &Callee) {
2043+
// Do not inline strictfp function into non-strictfp one. It would require
2044+
// conversion of all FP operations in host function to constrained intrinsics.
2045+
return !(Callee.getAttributes().hasFnAttr(Attribute::StrictFP) &&
2046+
!Caller.getAttributes().hasFnAttr(Attribute::StrictFP));
2047+
}
2048+
20422049
template<typename AttrClass>
20432050
static bool isEqual(const Function &Caller, const Function &Callee) {
20442051
return Caller.getFnAttribute(AttrClass::getKind()) ==
20452052
Callee.getFnAttribute(AttrClass::getKind());
20462053
}
20472054

2055+
static bool isEqual(const Function &Caller, const Function &Callee,
2056+
const StringRef &AttrName) {
2057+
return Caller.getFnAttribute(AttrName) == Callee.getFnAttribute(AttrName);
2058+
}
2059+
20482060
/// Compute the logical AND of the attributes of the caller and the
20492061
/// callee.
20502062
///

llvm/lib/Transforms/Utils/InlineFunction.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -2103,13 +2103,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
21032103
BasicBlock *OrigBB = CB.getParent();
21042104
Function *Caller = OrigBB->getParent();
21052105

2106-
// Do not inline strictfp function into non-strictfp one. It would require
2107-
// conversion of all FP operations in host function to constrained intrinsics.
2108-
if (CalledFunc->getAttributes().hasFnAttr(Attribute::StrictFP) &&
2109-
!Caller->getAttributes().hasFnAttr(Attribute::StrictFP)) {
2110-
return InlineResult::failure("incompatible strictfp attributes");
2111-
}
2112-
21132106
// GC poses two hazards to inlining, which only occur when the callee has GC:
21142107
// 1. If the caller has no GC, then the callee's GC must be propagated to the
21152108
// caller.
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

+6-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,12 @@ 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+
StringRef AttrName = Rule->getValueAsString("AttrName");
91+
if (AttrName.empty())
92+
OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
93+
else
94+
OS << " Ret &= " << FuncName << "(Caller, Callee, \"" << AttrName
95+
<< "\");\n";
9196
}
9297

9398
OS << "\n";

0 commit comments

Comments
 (0)