@@ -94,6 +94,10 @@ class PerformanceDiagnostics {
94
94
return visitFunction (function, perfConstr, /* parentLoc*/ nullptr );
95
95
}
96
96
97
+ bool visitFunctionEmbeddedSwift (SILFunction *function) {
98
+ return visitFunctionEmbeddedSwift (function, /* parentLoc*/ nullptr );
99
+ }
100
+
97
101
// / Check functions _without_ performance annotations.
98
102
// /
99
103
// / This is need to check closure arguments of called performance-annotated
@@ -104,6 +108,9 @@ class PerformanceDiagnostics {
104
108
bool visitFunction (SILFunction *function, PerformanceConstraints perfConstr,
105
109
LocWithParent *parentLoc);
106
110
111
+ bool visitFunctionEmbeddedSwift (SILFunction *function,
112
+ LocWithParent *parentLoc);
113
+
107
114
bool visitInst (SILInstruction *inst, PerformanceConstraints perfConstr,
108
115
LocWithParent *parentLoc);
109
116
@@ -150,6 +157,75 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
150
157
}
151
158
}
152
159
160
+ // / Prints Embedded Swift specific performance diagnostics (no existentials,
161
+ // / no metatypes, optionally no allocations) for \p function.
162
+ bool PerformanceDiagnostics::visitFunctionEmbeddedSwift (
163
+ SILFunction *function, LocWithParent *parentLoc) {
164
+ // Don't check generic functions in embedded Swift, they're about to be
165
+ // removed anyway.
166
+ if (function->getLoweredFunctionType ()->getSubstGenericSignature ())
167
+ return false ;
168
+
169
+ if (!function->isDefinition ())
170
+ return false ;
171
+
172
+ if (visitedFuncs.contains (function))
173
+ return false ;
174
+ visitedFuncs[function] = PerformanceConstraints::None;
175
+
176
+ NonErrorHandlingBlocks neBlocks (function);
177
+
178
+ for (SILBasicBlock &block : *function) {
179
+ for (SILInstruction &inst : block) {
180
+ if (visitInst (&inst, PerformanceConstraints::None, parentLoc)) {
181
+ if (inst.getLoc ().getSourceLoc ().isInvalid ()) {
182
+ auto demangledName = Demangle::demangleSymbolAsString (
183
+ inst.getFunction ()->getName (),
184
+ Demangle::DemangleOptions::SimplifiedUIDemangleOptions ());
185
+ llvm::errs () << " in function " << demangledName << " \n " ;
186
+ }
187
+ LLVM_DEBUG (llvm::dbgs () << inst << *inst.getFunction ());
188
+ return true ;
189
+ }
190
+
191
+ if (auto as = FullApplySite::isa (&inst)) {
192
+ LocWithParent asLoc (inst.getLoc ().getSourceLoc (), parentLoc);
193
+ LocWithParent *loc = &asLoc;
194
+ if (parentLoc &&
195
+ asLoc.loc == inst.getFunction ()->getLocation ().getSourceLoc ())
196
+ loc = parentLoc;
197
+
198
+ for (SILFunction *callee : bca->getCalleeList (as)) {
199
+ if (visitFunctionEmbeddedSwift (callee, loc))
200
+ return true ;
201
+ }
202
+ } else if (auto *bi = dyn_cast<BuiltinInst>(&inst)) {
203
+ PrettyStackTracePerformanceDiagnostics stackTrace (
204
+ " visitFunction::BuiltinInst (once, once with context)" , &inst);
205
+
206
+ switch (bi->getBuiltinInfo ().ID ) {
207
+ case BuiltinValueKind::Once:
208
+ case BuiltinValueKind::OnceWithContext:
209
+ if (auto *fri = dyn_cast<FunctionRefInst>(bi->getArguments ()[1 ])) {
210
+ LocWithParent asLoc (bi->getLoc ().getSourceLoc (), parentLoc);
211
+ LocWithParent *loc = &asLoc;
212
+ if (parentLoc &&
213
+ asLoc.loc == bi->getFunction ()->getLocation ().getSourceLoc ())
214
+ loc = parentLoc;
215
+
216
+ if (visitFunctionEmbeddedSwift (fri->getReferencedFunction (), loc))
217
+ return true ;
218
+ }
219
+ break ;
220
+ default :
221
+ break ;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ return false ;
227
+ }
228
+
153
229
// / Prints performance diagnostics for \p function.
154
230
bool PerformanceDiagnostics::visitFunction (SILFunction *function,
155
231
PerformanceConstraints perfConstr,
@@ -438,6 +514,18 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
438
514
return true ;
439
515
}
440
516
}
517
+
518
+ if (module .getOptions ().NoAllocations ) {
519
+ if (impact & RuntimeEffect::Allocating) {
520
+ PrettyStackTracePerformanceDiagnostics stackTrace (" allocation" , inst);
521
+ if (impactType) {
522
+ diagnose (loc, diag::embedded_swift_allocating_type, impactType.getASTType ());
523
+ } else {
524
+ diagnose (loc, diag::embedded_swift_allocating);
525
+ }
526
+ return true ;
527
+ }
528
+ }
441
529
}
442
530
443
531
if (perfConstr == PerformanceConstraints::None ||
@@ -585,19 +673,6 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
585
673
void PerformanceDiagnostics::checkNonAnnotatedFunction (SILFunction *function) {
586
674
for (SILBasicBlock &block : *function) {
587
675
for (SILInstruction &inst : block) {
588
- if (function->getModule ().getOptions ().EmbeddedSwift ) {
589
- auto loc = LocWithParent (inst.getLoc ().getSourceLoc (), nullptr );
590
- if (visitInst (&inst, PerformanceConstraints::None, &loc)) {
591
- if (inst.getLoc ().getSourceLoc ().isInvalid ()) {
592
- auto demangledName = Demangle::demangleSymbolAsString (
593
- inst.getFunction ()->getName (),
594
- Demangle::DemangleOptions::SimplifiedUIDemangleOptions ());
595
- llvm::errs () << " in function " << demangledName << " \n " ;
596
- }
597
- LLVM_DEBUG (llvm::dbgs () << inst << *inst.getFunction ());
598
- }
599
- }
600
-
601
676
auto as = FullApplySite::isa (&inst);
602
677
if (!as)
603
678
continue ;
@@ -701,16 +776,54 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
701
776
if (function.wasDeserializedCanonical ())
702
777
continue ;
703
778
704
- // Don't check generic functions in embedded Swift, they're about to be
705
- // removed anyway.
706
- if (getModule ()->getOptions ().EmbeddedSwift &&
707
- function.getLoweredFunctionType ()->getSubstGenericSignature ())
708
- continue ;
709
-
710
779
if (function.getPerfConstraints () == PerformanceConstraints::None) {
711
780
diagnoser.checkNonAnnotatedFunction (&function);
712
781
}
713
782
}
783
+
784
+ if (getModule ()->getOptions ().EmbeddedSwift ) {
785
+ // Run embedded Swift SIL checks for metatype/existential use, and
786
+ // allocation use (under -no-allocations mode). Try to start with public
787
+ // and exported functions to get better call tree information.
788
+ SmallVector<SILFunction *, 8 > externallyVisibleFunctions;
789
+ SmallVector<SILFunction *, 8 > vtableMembers;
790
+ SmallVector<SILFunction *, 8 > others;
791
+ SmallVector<SILFunction *, 8 > constructorsAndDestructors;
792
+
793
+ for (SILFunction &function : *module ) {
794
+ auto func = function.getLocation ().getAsASTNode <AbstractFunctionDecl>();
795
+ if (func) {
796
+ if (isa<DestructorDecl>(func) || isa<ConstructorDecl>(func)) {
797
+ constructorsAndDestructors.push_back (&function);
798
+ continue ;
799
+ }
800
+ if (getMethodDispatch (func) == MethodDispatch::Class) {
801
+ vtableMembers.push_back (&function);
802
+ continue ;
803
+ }
804
+ }
805
+
806
+ if (function.isPossiblyUsedExternally ()) {
807
+ externallyVisibleFunctions.push_back (&function);
808
+ continue ;
809
+ }
810
+
811
+ others.push_back (&function);
812
+ }
813
+
814
+ for (SILFunction *function : externallyVisibleFunctions) {
815
+ diagnoser.visitFunctionEmbeddedSwift (function);
816
+ }
817
+ for (SILFunction *function : vtableMembers) {
818
+ diagnoser.visitFunctionEmbeddedSwift (function);
819
+ }
820
+ for (SILFunction *function : others) {
821
+ diagnoser.visitFunctionEmbeddedSwift (function);
822
+ }
823
+ for (SILFunction *function : constructorsAndDestructors) {
824
+ diagnoser.visitFunctionEmbeddedSwift (function);
825
+ }
826
+ }
714
827
}
715
828
};
716
829
0 commit comments