Skip to content

Commit f6b1775

Browse files
committed
[nfc][opt] Add more stack traces and make them more specific.
1 parent a58cc2f commit f6b1775

File tree

1 file changed

+78
-17
lines changed

1 file changed

+78
-17
lines changed

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "swift/AST/SemanticAttrs.h"
1616
#include "swift/SIL/BasicBlockDatastructures.h"
1717
#include "swift/SIL/InstructionUtils.h"
18-
#include "swift/SIL/PrettyStackTrace.h"
1918
#include "swift/SIL/ApplySite.h"
2019
#include "swift/SILOptimizer/Analysis/ArraySemantic.h"
2120
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
@@ -27,6 +26,41 @@ using namespace swift;
2726

2827
namespace {
2928

29+
class PrettyStackTracePerformanceDiagnostics
30+
: public llvm::PrettyStackTraceEntry {
31+
const SILNode *node;
32+
const char *action;
33+
34+
public:
35+
PrettyStackTracePerformanceDiagnostics(const char *action, SILNodePointer node)
36+
: node(node), action(action) {}
37+
38+
virtual void print(llvm::raw_ostream &OS) const override {
39+
OS << "While " << action << " -- visiting node ";
40+
node->print(OS);
41+
42+
if (auto inst = dyn_cast<SILInstruction>(node)) {
43+
OS << "While visiting instruction in function ";
44+
inst->getFunction()->print(OS);
45+
}
46+
}
47+
};
48+
49+
class PrettyStackTraceSILGlobal
50+
: public llvm::PrettyStackTraceEntry {
51+
const SILGlobalVariable *node;
52+
const char *action;
53+
54+
public:
55+
PrettyStackTraceSILGlobal(const char *action, SILGlobalVariable *node)
56+
: node(node), action(action) {}
57+
58+
virtual void print(llvm::raw_ostream &OS) const override {
59+
OS << "While " << action << " -- visiting node ";
60+
node->print(OS);
61+
}
62+
};
63+
3064
/// Issues performance diagnostics for functions which are annotated with
3165
/// performance annotations, like @_noLocks, @_noAllocation.
3266
///
@@ -120,9 +154,6 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
120154
bool PerformanceDiagnostics::visitFunction(SILFunction *function,
121155
PerformanceConstraints perfConstr,
122156
LocWithParent *parentLoc) {
123-
PrettyStackTraceSILFunction stackTrace(
124-
"Running performance diangostics on (visiting) ", function);
125-
126157
if (!function->isDefinition())
127158
return false;
128159

@@ -160,8 +191,9 @@ bool PerformanceDiagnostics::visitFunction(SILFunction *function,
160191
if (visitCallee(&inst, bca->getCalleeList(as), perfConstr, parentLoc))
161192
return true;
162193
} else if (auto *bi = dyn_cast<BuiltinInst>(&inst)) {
163-
PrettyStackTraceSILNode biStackTrace(
164-
"Validating built in (once, once with context)", bi);
194+
PrettyStackTracePerformanceDiagnostics stackTrace(
195+
"visitFunction::BuiltinInst (once, once with context)", &inst);
196+
165197
switch (bi->getBuiltinInfo().ID) {
166198
case BuiltinValueKind::Once:
167199
case BuiltinValueKind::OnceWithContext:
@@ -210,8 +242,6 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
210242
SILInstruction *callInst,
211243
PerformanceConstraints perfConstr,
212244
LocWithParent *parentLoc) {
213-
PrettyStackTraceSILNode closureStackTrace("Validating closure", closure);
214-
215245
// Walk through the definition of the closure until we find the "underlying"
216246
// function_ref instruction.
217247
while (!isa<FunctionRefInst>(closure)) {
@@ -234,6 +264,9 @@ bool PerformanceDiagnostics::checkClosureValue(SILValue closure,
234264
// the call site.
235265
return false;
236266
} else {
267+
PrettyStackTracePerformanceDiagnostics stackTrace(
268+
"validating closure (function ref, callee) - unkown callee", callInst);
269+
237270
diagnose(LocWithParent(callInst->getLoc().getSourceLoc(), parentLoc), diag::performance_unknown_callees);
238271
return true;
239272
}
@@ -251,14 +284,14 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
251284
CalleeList callees,
252285
PerformanceConstraints perfConstr,
253286
LocWithParent *parentLoc) {
254-
PrettyStackTraceSILNode callStackTrace("Validating callee", callInst);
255-
256287
LocWithParent asLoc(callInst->getLoc().getSourceLoc(), parentLoc);
257288
LocWithParent *loc = &asLoc;
258289
if (parentLoc && asLoc.loc == callInst->getFunction()->getLocation().getSourceLoc())
259290
loc = parentLoc;
260291

261292
if (callees.isIncomplete()) {
293+
PrettyStackTracePerformanceDiagnostics stackTrace("incomplete", callInst);
294+
262295
diagnose(*loc, diag::performance_unknown_callees);
263296
return true;
264297
}
@@ -273,6 +306,8 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
273306
return false;
274307

275308
if (!callee->isDefinition()) {
309+
PrettyStackTracePerformanceDiagnostics stackTrace("incomplete", callInst);
310+
276311
diagnose(*loc, diag::performance_callee_unavailable);
277312
return true;
278313
}
@@ -291,8 +326,6 @@ bool PerformanceDiagnostics::visitCallee(SILInstruction *callInst,
291326
}
292327

293328
static bool metatypeUsesAreNotRelevant(MetatypeInst *mt) {
294-
PrettyStackTraceSILNode mtStackTrace("Validating metatype", mt);
295-
296329
for (Operand *use : mt->getUses()) {
297330
if (auto *bi = dyn_cast<BuiltinInst>(use->getUser())) {
298331
switch (bi->getBuiltinInfo().ID) {
@@ -315,15 +348,15 @@ static bool metatypeUsesAreNotRelevant(MetatypeInst *mt) {
315348
bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
316349
PerformanceConstraints perfConstr,
317350
LocWithParent *parentLoc) {
318-
PrettyStackTraceSILNode stackTrace("validating sil instruction (visiting)", inst);
319-
320351
SILType impactType;
321352
RuntimeEffect impact = getRuntimeEffect(inst, impactType);
322353
LocWithParent loc(inst->getLoc().getSourceLoc(), parentLoc);
323354

324355
if (impact & RuntimeEffect::Casting) {
325356
// TODO: be more specific on casting.
326357
// E.g. distinguish locking and allocating dynamic casts, etc.
358+
PrettyStackTracePerformanceDiagnostics stackTrace("bad cast", inst);
359+
327360
diagnose(loc, diag::performance_dynamic_casting);
328361
return true;
329362
}
@@ -333,21 +366,30 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
333366

334367
// Try to give a good error message by looking which type of code it is.
335368
switch (inst->getKind()) {
336-
case SILInstructionKind::KeyPathInst:
369+
case SILInstructionKind::KeyPathInst: {
370+
PrettyStackTracePerformanceDiagnostics stackTrace("key path", inst);
337371
diagnose(loc, diag::performance_metadata, "using KeyPath");
338372
break;
373+
}
339374
case SILInstructionKind::AllocGlobalInst:
340-
case SILInstructionKind::GlobalValueInst:
375+
case SILInstructionKind::GlobalValueInst: {
376+
PrettyStackTracePerformanceDiagnostics stackTrace(
377+
"AllocGlobalInst | GlobalValueInst", inst);
341378
diagnose(loc, diag::performance_metadata, "global or static variables");
342379
break;
380+
}
343381
case SILInstructionKind::PartialApplyInst: {
382+
PrettyStackTracePerformanceDiagnostics stackTrace(
383+
"PartialApplyInst", inst);
344384
diagnose(loc, diag::performance_metadata,
345385
"generic closures or local functions");
346386
break;
347387
}
348388
case SILInstructionKind::ApplyInst:
349389
case SILInstructionKind::TryApplyInst:
350390
case SILInstructionKind::BeginApplyInst: {
391+
PrettyStackTracePerformanceDiagnostics stackTrace(
392+
"ApplyInst | TryApplyInst | BeginApplyInst", inst);
351393
diagnose(loc, diag::performance_metadata, "generic function calls");
352394
break;
353395
}
@@ -359,16 +401,23 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
359401
// We didn't recognize the instruction, so try to give an error message
360402
// based on the involved type.
361403
if (impactType) {
404+
PrettyStackTracePerformanceDiagnostics stackTrace(
405+
"impactType (unrecognized instruction)", inst);
362406
diagnose(loc, diag::performance_metadata_type, impactType.getASTType());
363407
break;
364408
}
365409
// The default error message.
410+
PrettyStackTracePerformanceDiagnostics stackTrace(
411+
"default error (fallthrough, unkown inst)", inst);
366412
diagnose(loc, diag::performance_metadata, "this code pattern");
367413
break;
368414
}
369415
return true;
370416
}
371417
if (impact & RuntimeEffect::Allocating) {
418+
PrettyStackTracePerformanceDiagnostics stackTrace(
419+
"found allocation effect", inst);
420+
372421
switch (inst->getKind()) {
373422
case SILInstructionKind::BeginApplyInst:
374423
// Not all begin_applys necessarily allocate. But it's difficult to
@@ -389,6 +438,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
389438
return true;
390439
}
391440
if (impact & RuntimeEffect::Deallocating) {
441+
PrettyStackTracePerformanceDiagnostics stackTrace(
442+
"found deallocation effect", inst);
443+
392444
if (impactType) {
393445
switch (inst->getKind()) {
394446
case SILInstructionKind::StoreInst:
@@ -409,6 +461,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
409461
return true;
410462
}
411463
if (impact & RuntimeEffect::ObjectiveC) {
464+
PrettyStackTracePerformanceDiagnostics stackTrace(
465+
"found objc effect", inst);
466+
412467
diagnose(loc, diag::performance_objectivec);
413468
return true;
414469
}
@@ -417,6 +472,9 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
417472
return false;
418473

419474
// Handle locking-only effects.
475+
476+
PrettyStackTracePerformanceDiagnostics stackTrace(
477+
"found locking or ref counting effect", inst);
420478

421479
if (impact & RuntimeEffect::Locking) {
422480
if (inst->getFunction()->isGlobalInit()) {
@@ -461,7 +519,7 @@ void PerformanceDiagnostics::checkNonAnnotatedFunction(SILFunction *function) {
461519
}
462520
}
463521

464-
void PerformanceDiagnostics::diagnose(LocWithParent loc, Diagnostic &&D) {
522+
void PerformanceDiagnostics::diagnose(LocWithParent loc, Diagnostic &&D) {
465523
// Start with a valid location in the call tree.
466524
LocWithParent *validLoc = &loc;
467525
while (!validLoc->loc.isValid() && validLoc->parent) {
@@ -498,6 +556,9 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
498556
// Check that @_section, @_silgen_name is only on constant globals
499557
for (SILGlobalVariable &g : module->getSILGlobals()) {
500558
if (!g.getStaticInitializerValue() && g.mustBeInitializedStatically()) {
559+
PrettyStackTraceSILGlobal stackTrace(
560+
"global inst", &g);
561+
501562
auto *decl = g.getDecl();
502563
if (g.getSectionAttr()) {
503564
module->getASTContext().Diags.diagnose(

0 commit comments

Comments
 (0)