Skip to content

Commit 481381b

Browse files
committed
PerformanceDiagnostics: correctly handle initializers of global variables
So far, initializers of global variables were ignored. The fix is to visit the called initializer of the builtin `once`. rdar://94780620
1 parent 9d75c30 commit 481381b

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class PerformanceDiagnostics {
6464
bool visitInst(SILInstruction *inst, PerformanceConstraints perfConstr,
6565
LocWithParent *parentLoc);
6666

67-
bool visitCallee(FullApplySite as, PerformanceConstraints perfConstr,
68-
LocWithParent *parentLoc);
67+
bool visitCallee(SILInstruction *callInst, CalleeList callees,
68+
PerformanceConstraints perfConstr, LocWithParent *parentLoc);
6969

7070
template<typename ...ArgTypes>
7171
void diagnose(LocWithParent loc, Diag<ArgTypes...> ID,
@@ -108,21 +108,37 @@ bool PerformanceDiagnostics::visitFunction(SILFunction *function,
108108
continue;
109109

110110
// Recursively walk into the callees.
111-
if (visitCallee(as, perfConstr, parentLoc))
111+
if (visitCallee(&inst, bca->getCalleeList(as), perfConstr, parentLoc))
112112
return true;
113+
} else if (auto *bi = dyn_cast<BuiltinInst>(&inst)) {
114+
switch (bi->getBuiltinInfo().ID) {
115+
case BuiltinValueKind::Once:
116+
case BuiltinValueKind::OnceWithContext:
117+
if (auto *fri = dyn_cast<FunctionRefInst>(bi->getArguments()[1])) {
118+
if (visitCallee(bi, fri->getReferencedFunction(), perfConstr, parentLoc))
119+
return true;
120+
} else {
121+
LocWithParent loc(inst.getLoc().getSourceLoc(), parentLoc);
122+
diagnose(loc, diag::performance_unknown_callees);
123+
return true;
124+
}
125+
break;
126+
default:
127+
break;
128+
}
113129
}
114130
}
115131
}
116132
return false;
117133
}
118134

119-
bool PerformanceDiagnostics::visitCallee(FullApplySite as,
120-
PerformanceConstraints perfConstr,
121-
LocWithParent *parentLoc) {
122-
CalleeList callees = bca->getCalleeList(as);
123-
LocWithParent asLoc(as.getLoc().getSourceLoc(), parentLoc);
135+
bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
136+
CalleeList callees,
137+
PerformanceConstraints perfConstr,
138+
LocWithParent *parentLoc) {
139+
LocWithParent asLoc(callInst->getLoc().getSourceLoc(), parentLoc);
124140
LocWithParent *loc = &asLoc;
125-
if (parentLoc && asLoc.loc == as.getFunction()->getLocation().getSourceLoc())
141+
if (parentLoc && asLoc.loc == callInst->getFunction()->getLocation().getSourceLoc())
126142
loc = parentLoc;
127143

128144
if (callees.isIncomplete()) {

test/SILOptimizer/performance-annotations.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,18 @@ func memoryLayout() -> Int? {
148148
return MemoryLayout<GenStruct<Int>>.size
149149
}
150150

151+
class H {
152+
var hash: Int { 27 }
153+
}
154+
155+
struct MyStruct {
156+
static var v: Int = { // expected-note {{called from here}}
157+
return H().hash // expected-error {{Using type 'H' can cause metadata allocation or locks}}
158+
}()
159+
}
160+
161+
@_noAllocation
162+
func globalWithInitializer(x: MyStruct) {
163+
_ = MyStruct.v // expected-note {{called from here}}
164+
}
165+

0 commit comments

Comments
 (0)