Skip to content

Commit 5377615

Browse files
committed
MSVC inliner section behavior compat
1 parent c234717 commit 5377615

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

llvm/include/llvm/IR/Attributes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ def : CompatRule<"isEqual<UseSampleProfileAttr>">;
455455
def : CompatRule<"isEqual<NoProfileAttr>">;
456456
def : CompatRule<"checkDenormMode">;
457457
def : CompatRule<"checkStrictFP">;
458+
def : CompatRule<"checkSectionsMSVC">;
458459
def : CompatRuleStrAttr<"isEqual", "sign-return-address">;
459460
def : CompatRuleStrAttr<"isEqual", "sign-return-address-key">;
460461
def : CompatRuleStrAttr<"isEqual", "branch-protection-pauth-lr">;

llvm/lib/IR/Attributes.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,6 +2508,49 @@ static bool checkStrictFP(const Function &Caller, const Function &Callee) {
25082508
Caller.getAttributes().hasFnAttr(Attribute::StrictFP);
25092509
}
25102510

2511+
static bool checkSectionsMSVC(const Function &Caller, const Function &Callee) {
2512+
if (!Caller.getParent()->getTargetTriple().isWindowsMSVCEnvironment())
2513+
return true;
2514+
2515+
// Implement MSVC compatible cross-section inlining rules
2516+
StringRef CallerSection = Caller.getSection();
2517+
StringRef CalleeSection = Callee.getSection();
2518+
2519+
// sections match, inline ok
2520+
if (!CallerSection.compare(CalleeSection))
2521+
return true;
2522+
2523+
bool isCallerPaged = CallerSection.starts_with("PAGE");
2524+
bool isCalleePaged = CalleeSection.starts_with("PAGE");
2525+
2526+
// Prevent inlining of non-paged code into a paged caller
2527+
// Prevent inlining of paged code into non-paged caller
2528+
// Section names are compared only before the '$' separator if present
2529+
2530+
if (isCallerPaged) {
2531+
size_t CallerComparable = CallerSection.size();
2532+
size_t CalleeComparable = CalleeSection.size();
2533+
size_t CallerSep = CallerSection.find('$');
2534+
size_t CalleeSep = CalleeSection.find('$');
2535+
2536+
if (CallerSep != StringRef::npos)
2537+
CallerComparable = CallerSep;
2538+
if (CalleeSep != StringRef::npos)
2539+
CalleeComparable = CalleeSep;
2540+
if (CallerComparable != CalleeComparable)
2541+
return false;
2542+
2543+
StringRef CallerComparableSection =
2544+
CallerSection.substr(0, CallerComparable);
2545+
StringRef CalleeComparableSection =
2546+
CalleeSection.substr(0, CallerComparable);
2547+
return !CallerComparableSection.compare(CalleeComparableSection);
2548+
} else if (isCalleePaged)
2549+
return false;
2550+
2551+
return true;
2552+
}
2553+
25112554
template<typename AttrClass>
25122555
static bool isEqual(const Function &Caller, const Function &Callee) {
25132556
return Caller.getFnAttribute(AttrClass::getKind()) ==
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
; RUN: opt < %s -passes=inline -inline-threshold=100 -S | FileCheck %s
2+
; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=100 -S | FileCheck %s
3+
; RUN: opt < %s -mtriple=aarch64-windows-msvc -passes=inline -inline-threshold=100 -S | FileCheck %s -check-prefix=MSVC
4+
; RUN: opt < %s -mtriple=aarch64-windows-msvc -passes='cgscc(inline)' -inline-threshold=100 -S | FileCheck %s -check-prefix=MSVC
5+
6+
define i32 @nosection_callee(i32 %x) {
7+
%x1 = add i32 %x, 1
8+
%x2 = add i32 %x1, 1
9+
%x3 = add i32 %x2, 1
10+
call void @extern()
11+
ret i32 %x3
12+
}
13+
14+
define i32 @section_callee(i32 %x) section "FOO" {
15+
%x1 = add i32 %x, 1
16+
%x2 = add i32 %x1, 1
17+
%x3 = add i32 %x2, 1
18+
call void @extern()
19+
ret i32 %x3
20+
}
21+
22+
define i32 @sectionpostfix_callee(i32 %x) section "FOO$BBBB" {
23+
%x1 = add i32 %x, 1
24+
%x2 = add i32 %x1, 1
25+
%x3 = add i32 %x2, 1
26+
call void @extern()
27+
ret i32 %x3
28+
}
29+
30+
define i32 @paged_callee(i32 %x) section "PAGE" {
31+
%x1 = add i32 %x, 1
32+
%x2 = add i32 %x1, 1
33+
%x3 = add i32 %x2, 1
34+
call void @extern()
35+
ret i32 %x3
36+
}
37+
38+
define i32 @pagedpostfix_callee(i32 %x) section "PAGE$aaa" {
39+
%x1 = add i32 %x, 1
40+
%x2 = add i32 %x1, 1
41+
%x3 = add i32 %x2, 1
42+
call void @extern()
43+
ret i32 %x3
44+
}
45+
46+
define i32 @nosection_caller(i32 %y1) {
47+
%y2 = call i32 @nosection_callee(i32 %y1)
48+
%y3 = call i32 @section_callee(i32 %y2)
49+
%y4 = call i32 @sectionpostfix_callee(i32 %y3)
50+
%y5 = call i32 @paged_callee(i32 %y4)
51+
%y6 = call i32 @pagedpostfix_callee(i32 %y5)
52+
ret i32 %y6
53+
}
54+
55+
; CHECK-LABEL: @nosection_caller
56+
; CHECK-NOT: @nosection_callee
57+
; CHECK-NOT: @section_callee
58+
; CHECK-NOT: @sectionpostfix_callee
59+
; CHECK-NOT: @paged_callee
60+
; CHECK-NOT: @pagedpostfix_callee
61+
; MSVC-LABEL: @nosection_caller
62+
; MSVC-NOT: @nosection_callee
63+
; MSVC-NOT: @section_callee
64+
; MSVC-NOT: @sectionpostfix_callee
65+
; MSVC: @paged_callee
66+
; MSVC: @pagedpostfix_callee
67+
68+
define i32 @section_caller(i32 %y1) section "FOO" {
69+
%y2 = call i32 @nosection_callee(i32 %y1)
70+
%y3 = call i32 @section_callee(i32 %y2)
71+
%y4 = call i32 @sectionpostfix_callee(i32 %y3)
72+
%y5 = call i32 @paged_callee(i32 %y4)
73+
%y6 = call i32 @pagedpostfix_callee(i32 %y5)
74+
ret i32 %y6
75+
}
76+
77+
; CHECK-LABEL: @section_caller
78+
; CHECK-NOT: @nosection_callee
79+
; CHECK-NOT: @section_callee
80+
; CHECK-NOT: @sectionpostfix_callee
81+
; CHECK-NOT: @paged_callee
82+
; CHECK-NOT: @pagedpostfix_callee
83+
; MSVC-LABEL: @section_caller
84+
; MSVC-NOT: @nosection_callee
85+
; MSVC-NOT: @section_callee
86+
; MSVC-NOT: @sectionpostfix_callee
87+
; MSVC: @paged_callee
88+
; MSVC: @pagedpostfix_callee
89+
90+
define i32 @sectionpostfix_caller(i32 %y1) section "FOO$ZZZ" {
91+
%y2 = call i32 @nosection_callee(i32 %y1)
92+
%y3 = call i32 @section_callee(i32 %y2)
93+
%y4 = call i32 @sectionpostfix_callee(i32 %y3)
94+
%y5 = call i32 @paged_callee(i32 %y4)
95+
%y6 = call i32 @pagedpostfix_callee(i32 %y5)
96+
ret i32 %y6
97+
}
98+
99+
; CHECK-LABEL: @sectionpostfix_caller
100+
; CHECK-NOT: @nosection_callee
101+
; CHECK-NOT: @section_callee
102+
; CHECK-NOT: @sectionpostfix_callee
103+
; CHECK-NOT: @paged_callee
104+
; CHECK-NOT: @pagedpostfix_callee
105+
; MSVC-LABEL: @sectionpostfix_caller
106+
; MSVC-NOT: @nosection_callee
107+
; MSVC-NOT: @section_callee
108+
; MSVC-NOT: @sectionpostfix_callee
109+
; MSVC: @paged_callee
110+
; MSVC: @pagedpostfix_callee
111+
112+
define i32 @paged_caller(i32 %y1) section "PAGE" {
113+
%y2 = call i32 @nosection_callee(i32 %y1)
114+
%y3 = call i32 @section_callee(i32 %y2)
115+
%y4 = call i32 @sectionpostfix_callee(i32 %y3)
116+
%y5 = call i32 @paged_callee(i32 %y4)
117+
%y6 = call i32 @pagedpostfix_callee(i32 %y5)
118+
ret i32 %y6
119+
}
120+
121+
; CHECK-LABEL: @paged_caller
122+
; CHECK-NOT: @nosection_callee
123+
; CHECK-NOT: @section_callee
124+
; CHECK-NOT: @sectionpostfix_callee
125+
; CHECK-NOT: @paged_callee
126+
; CHECK-NOT: @pagedpostfix_callee
127+
; MSVC-LABEL: @paged_caller
128+
; MSVC: @nosection_callee
129+
; MSVC: @section_callee
130+
; MSVC: @sectionpostfix_callee
131+
; MSVC-NOT: @paged_callee
132+
; MSVC-NOT: @pagedpostfix_callee
133+
134+
define i32 @pagedpostfix_caller(i32 %y1) section "PAGE$ZZZ" {
135+
%y2 = call i32 @nosection_callee(i32 %y1)
136+
%y3 = call i32 @section_callee(i32 %y2)
137+
%y4 = call i32 @sectionpostfix_callee(i32 %y3)
138+
%y5 = call i32 @paged_callee(i32 %y4)
139+
%y6 = call i32 @pagedpostfix_callee(i32 %y5)
140+
ret i32 %y6
141+
}
142+
143+
; CHECK-LABEL: @pagedpostfix_caller
144+
; CHECK-NOT: @nosection_callee
145+
; CHECK-NOT: @section_callee
146+
; CHECK-NOT: @sectionpostfix_callee
147+
; CHECK-NOT: @paged_callee
148+
; CHECK-NOT: @pagedpostfix_callee
149+
; MSVC-LABEL: @pagedpostfix_caller
150+
; MSVC: @nosection_callee
151+
; MSVC: @section_callee
152+
; MSVC: @sectionpostfix_callee
153+
; MSVC-NOT: @paged_callee
154+
; MSVC-NOT: @pagedpostfix_callee
155+
156+
declare void @extern()
157+

0 commit comments

Comments
 (0)