Skip to content

Commit cf69a9b

Browse files
committed
Move PostOrderFunctionAttr pass before GlobalOpt to realize localization of variables based on norecurse attribute
1 parent 7e471c1 commit cf69a9b

File tree

3 files changed

+97
-5
lines changed

3 files changed

+97
-5
lines changed

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,7 +2022,11 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
20222022
/*Summary=*/nullptr,
20232023
PGOOpt && PGOOpt->Action == PGOOptions::SampleUse));
20242024

2025-
// Optimize globals again after we ran the inliner.
2025+
MPM.addPass(
2026+
createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass()));
2027+
2028+
// Optimize globals again after we ran the inliner and function attribute
2029+
// inference.
20262030
MPM.addPass(GlobalOptPass());
20272031

20282032
// Run the OpenMPOpt pass again after global optimizations.
@@ -2075,9 +2079,6 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
20752079
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM),
20762080
PTO.EagerlyInvalidateAnalyses));
20772081

2078-
MPM.addPass(
2079-
createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass()));
2080-
20812082
// Require the GlobalsAA analysis for the module so we can query it within
20822083
// MainFPM.
20832084
if (EnableGlobalAnalyses) {

llvm/test/Other/new-pm-lto-defaults.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
; CHECK-O23SZ-NEXT: Running pass: InlinerPass
8484
; CHECK-O23SZ-NEXT: Running pass: InlinerPass
8585
; CHECK-O23SZ-NEXT: Invalidating analysis: InlineAdvisorAnalysis
86+
; CHECK-O23SZ-NEXT: Running pass: PostOrderFunctionAttrsPass on (foo)
8687
; CHECK-O23SZ-NEXT: Running pass: GlobalOptPass
8788
; CHECK-O23SZ-NEXT: Running pass: OpenMPOptPass
8889
; CHECK-O23SZ-NEXT: Running pass: GlobalDCEPass
@@ -98,7 +99,6 @@
9899
; CHECK-O23SZ-NEXT: Running analysis: LazyValueAnalysis
99100
; CHECK-O23SZ-NEXT: Running pass: SROAPass on foo
100101
; CHECK-O23SZ-NEXT: Running pass: TailCallElimPass on foo
101-
; CHECK-O23SZ-NEXT: Running pass: PostOrderFunctionAttrsPass on (foo)
102102
; CHECK-O23SZ-NEXT: Running pass: RequireAnalysisPass<{{.*}}GlobalsAA
103103
; CHECK-O23SZ-NEXT: Running analysis: GlobalsAA on [module]
104104
; CHECK-O23SZ-NEXT: Running analysis: CallGraphAnalysis on [module]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 5
2+
; RUN: opt -passes="wholeprogramdevirt,globalopt" -whole-program-visibility -S %s -o - | FileCheck %s --check-prefix=CHECK-BEFORE
3+
; RUN: opt -passes="wholeprogramdevirt,function-attrs,globalopt" -whole-program-visibility -S %s -o - | FileCheck %s --check-prefix=CHECK-AFTER
4+
5+
; This test demonstrates a case simulating the pass order in LTO default
6+
; pass pipeline. In this case, there is an indirect call in a function
7+
; which is only resolved by whole program devirtualization.
8+
; This call resolution leads Function Attr pass to infer norecurse attribute
9+
; for this function. This function stores a global variable (only once) and
10+
; there is a use of this global variable within this function.
11+
; Based on the norecurse attribute, GlobalOpt pass can localize this global
12+
; variable. However, in current pass pipeline, the pass sequence after whole
13+
; program devirtualization is as follows:
14+
; Whole Program Devirtualization -> (more passes) -> GlobalOpt -> (more passes)
15+
; -> PostOrderFunctionAttr
16+
; This test verifies that adding Function Attribute pass between Whole program
17+
; devirtualization and GlobalOpt would help in this kind of cases.
18+
19+
; Global variable which should become unused after GlobalOpt
20+
@testptr = internal unnamed_addr global double 0.0, align 8
21+
22+
declare double @sqrt(double) readnone nounwind nocallback
23+
declare { ptr, i1 } @llvm.type.checked.load(ptr, i32, metadata)
24+
@llvm.compiler.used = appending global [1 x ptr] [ptr @call_through_fp], section "llvm.metadata"
25+
26+
; Indirect call target
27+
define dso_local void @target(ptr %a) !type !0 {
28+
; CHECK-BEFORE-LABEL: define dso_local void @target(
29+
; CHECK-BEFORE-SAME: ptr [[A:%.*]]) !type [[META0:![0-9]+]] {
30+
; CHECK-BEFORE-NEXT: ret void
31+
;
32+
; CHECK-AFTER: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
33+
; CHECK-AFTER-LABEL: define dso_local void @target(
34+
; CHECK-AFTER-SAME: ptr readnone captures(none) [[A:%.*]]) #[[ATTR1:[0-9]+]] !type [[META0:![0-9]+]] {
35+
; CHECK-AFTER-NEXT: ret void
36+
;
37+
ret void
38+
}
39+
40+
@vtable_for_target = constant { ptr } { ptr @target }, !type !0
41+
42+
define dso_local void @call_through_fp() {
43+
; CHECK-BEFORE-LABEL: define dso_local void @call_through_fp() {
44+
; CHECK-BEFORE-NEXT: [[ENTRY:.*:]]
45+
; CHECK-BEFORE-NEXT: [[VTABLE_ENTRY:%.*]] = getelementptr { ptr }, ptr @vtable_for_target, i32 0, i32 0
46+
; CHECK-BEFORE-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[VTABLE_ENTRY]], i32 0
47+
; CHECK-BEFORE-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
48+
; CHECK-BEFORE-NEXT: call void @target(ptr null)
49+
; CHECK-BEFORE-NEXT: [[VAL:%.*]] = fadd double 1.000000e+00, 2.000000e+00
50+
; CHECK-BEFORE-NEXT: store double [[VAL]], ptr @testptr, align 8
51+
; CHECK-BEFORE-NEXT: [[X:%.*]] = load double, ptr @testptr, align 8
52+
; CHECK-BEFORE-NEXT: [[RES2:%.*]] = call double @sqrt(double [[X]])
53+
; CHECK-BEFORE-NEXT: ret void
54+
;
55+
; CHECK-AFTER: Function Attrs: norecurse nounwind memory(readwrite, argmem: none, inaccessiblemem: none)
56+
; CHECK-AFTER-LABEL: define dso_local void @call_through_fp(
57+
; CHECK-AFTER-SAME: ) #[[ATTR2:[0-9]+]] {
58+
; CHECK-AFTER-NEXT: [[ENTRY:.*:]]
59+
; CHECK-AFTER-NEXT: [[TESTPTR:%.*]] = alloca double, align 8
60+
; CHECK-AFTER-NEXT: store double 0.000000e+00, ptr [[TESTPTR]], align 8
61+
; CHECK-AFTER-NEXT: [[VTABLE_ENTRY:%.*]] = getelementptr { ptr }, ptr @vtable_for_target, i32 0, i32 0
62+
; CHECK-AFTER-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[VTABLE_ENTRY]], i32 0
63+
; CHECK-AFTER-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
64+
; CHECK-AFTER-NEXT: call void @target(ptr null)
65+
; CHECK-AFTER-NEXT: [[VAL:%.*]] = fadd double 1.000000e+00, 2.000000e+00
66+
; CHECK-AFTER-NEXT: store double [[VAL]], ptr [[TESTPTR]], align 8
67+
; CHECK-AFTER-NEXT: [[X:%.*]] = load double, ptr [[TESTPTR]], align 8
68+
; CHECK-AFTER-NEXT: [[RES2:%.*]] = call double @sqrt(double [[X]])
69+
; CHECK-AFTER-NEXT: ret void
70+
;
71+
entry:
72+
%vtable_entry = getelementptr { ptr }, ptr @vtable_for_target, i32 0, i32 0
73+
%res = call { ptr, i1 } @llvm.type.checked.load(ptr %vtable_entry, i32 0, metadata !"typeid")
74+
%fptr = extractvalue { ptr, i1 } %res, 0
75+
call void %fptr(ptr null)
76+
%val = fadd double 1.0, 2.0
77+
store double %val, ptr @testptr
78+
%x = load double, ptr @testptr
79+
%res2 = call double @sqrt(double %x)
80+
ret void
81+
}
82+
83+
!0 = !{i32 0, !"typeid", i32 0}
84+
!llvm.type.metadata = !{!1}
85+
!1 = !{ptr @vtable_for_target, !"typeid", i64 0}
86+
87+
;.
88+
; CHECK-BEFORE: [[META0]] = !{i32 0, !"typeid", i32 0}
89+
;.
90+
; CHECK-AFTER: [[META0]] = !{i32 0, !"typeid", i32 0}
91+
;.

0 commit comments

Comments
 (0)