|
25 | 25 | #include "llvm/Demangle/Demangle.h"
|
26 | 26 | #include "llvm/IR/Constants.h"
|
27 | 27 | #include "llvm/IR/Function.h"
|
| 28 | +#include "llvm/IR/InstIterator.h" |
| 29 | +#include "llvm/IR/IntrinsicInst.h" |
28 | 30 | #include "llvm/IR/Module.h"
|
29 | 31 | #include "llvm/IR/PassInstrumentation.h"
|
30 | 32 | #include "llvm/IR/PassManager.h"
|
@@ -139,6 +141,11 @@ static cl::opt<std::string> IRDumpDirectory(
|
139 | 141 | "files in this directory rather than written to stderr"),
|
140 | 142 | cl::Hidden, cl::value_desc("filename"));
|
141 | 143 |
|
| 144 | +static cl::opt<bool> |
| 145 | + DroppedVarStats("dropped-variable-stats", cl::Hidden, |
| 146 | + cl::desc("Dump dropped debug variables stats"), |
| 147 | + cl::init(false)); |
| 148 | + |
142 | 149 | template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
|
143 | 150 | const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
|
144 | 151 | return IRPtr ? *IRPtr : nullptr;
|
@@ -2441,19 +2448,101 @@ void DotCfgChangeReporter::registerCallbacks(
|
2441 | 2448 | }
|
2442 | 2449 | }
|
2443 | 2450 |
|
| 2451 | +void DroppedVariableStats::registerCallbacks( |
| 2452 | + PassInstrumentationCallbacks &PIC) { |
| 2453 | + if (!DroppedVarStats) |
| 2454 | + return; |
| 2455 | + |
| 2456 | + PIC.registerBeforeNonSkippedPassCallback( |
| 2457 | + [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); }); |
| 2458 | + PIC.registerAfterPassCallback( |
| 2459 | + [this](StringRef P, Any IR, const PreservedAnalyses &PA) { |
| 2460 | + return this->runAfterPass(P, IR, PA); |
| 2461 | + }); |
| 2462 | +} |
| 2463 | + |
| 2464 | +void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) { |
| 2465 | + DebugVariablesBefore.push_back(llvm::DenseSet<VarID>()); |
| 2466 | + DebugVariablesAfter.push_back(llvm::DenseSet<VarID>()); |
| 2467 | + if (auto *M = unwrapIR<Module>(IR)) |
| 2468 | + return this->runOnModule(M, true); |
| 2469 | + if (auto *F = unwrapIR<Function>(IR)) |
| 2470 | + return this->runOnFunction(F, true); |
| 2471 | + return; |
| 2472 | +} |
| 2473 | + |
| 2474 | +void DroppedVariableStats::runOnFunction(const Function *F, bool Before) { |
| 2475 | + auto &VarIDs = (Before ? DebugVariablesBefore : DebugVariablesAfter).back(); |
| 2476 | + for (const auto &I : instructions(F)) { |
| 2477 | + for (DbgRecord &DR : I.getDbgRecordRange()) { |
| 2478 | + if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) { |
| 2479 | + auto *DbgVar = Dbg->getVariable(); |
| 2480 | + StringRef UniqueName = DbgVar->getName(); |
| 2481 | + auto DbgLoc = DR.getDebugLoc(); |
| 2482 | + unsigned Line = DbgVar->getLine(); |
| 2483 | + VarID Key{cast<DILocalScope>(DbgVar->getScope()), |
| 2484 | + DbgLoc->getInlinedAtScope(), UniqueName, Line}; |
| 2485 | + VarIDs.insert(Key); |
| 2486 | + } |
| 2487 | + } |
| 2488 | + } |
| 2489 | +} |
| 2490 | + |
| 2491 | +void DroppedVariableStats::runOnModule(const Module *M, bool Before) { |
| 2492 | + for (auto &F : *M) |
| 2493 | + runOnFunction(&F, Before); |
| 2494 | +} |
| 2495 | + |
| 2496 | +void DroppedVariableStats::removeVarFromAllSets(VarID Var) { |
| 2497 | + // Do not remove Var from the last element, it will be popped from the stack |
| 2498 | + // anyway. |
| 2499 | + for (auto *It = DebugVariablesBefore.begin(); |
| 2500 | + It != DebugVariablesBefore.end() - 1; It++) |
| 2501 | + It->erase(Var); |
| 2502 | +} |
| 2503 | + |
| 2504 | +void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR, |
| 2505 | + const PreservedAnalyses &PA) { |
| 2506 | + unsigned DroppedCount = 0; |
| 2507 | + std::string PassLevel; |
| 2508 | + std::string FuncOrModName; |
| 2509 | + if (auto *M = unwrapIR<Module>(IR)) { |
| 2510 | + this->runOnModule(M, false); |
| 2511 | + PassLevel = "Module"; |
| 2512 | + FuncOrModName = M->getName(); |
| 2513 | + } else if (auto *F = unwrapIR<Function>(IR)) { |
| 2514 | + this->runOnFunction(F, false); |
| 2515 | + PassLevel = "Function"; |
| 2516 | + FuncOrModName = F->getName(); |
| 2517 | + } else { |
| 2518 | + return; |
| 2519 | + } |
| 2520 | + for (auto Var : DebugVariablesBefore.back()) |
| 2521 | + if (!DebugVariablesAfter.back().contains(Var)) { |
| 2522 | + DroppedCount++; |
| 2523 | + removeVarFromAllSets(Var); |
| 2524 | + } |
| 2525 | + if (DroppedCount > 0) |
| 2526 | + llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", " |
| 2527 | + << FuncOrModName << "\n"; |
| 2528 | + DebugVariablesBefore.pop_back(); |
| 2529 | + DebugVariablesAfter.pop_back(); |
| 2530 | + return; |
| 2531 | +} |
| 2532 | + |
2444 | 2533 | StandardInstrumentations::StandardInstrumentations(
|
2445 | 2534 | LLVMContext &Context, bool DebugLogging, bool VerifyEach,
|
2446 | 2535 | PrintPassOptions PrintPassOpts)
|
2447 |
| - : PrintPass(DebugLogging, PrintPassOpts), |
2448 |
| - OptNone(DebugLogging), |
| 2536 | + : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging), |
2449 | 2537 | OptPassGate(Context),
|
2450 | 2538 | PrintChangedIR(PrintChanged == ChangePrinter::Verbose),
|
2451 | 2539 | PrintChangedDiff(PrintChanged == ChangePrinter::DiffVerbose ||
|
2452 | 2540 | PrintChanged == ChangePrinter::ColourDiffVerbose,
|
2453 | 2541 | PrintChanged == ChangePrinter::ColourDiffVerbose ||
|
2454 | 2542 | PrintChanged == ChangePrinter::ColourDiffQuiet),
|
2455 | 2543 | WebsiteChangeReporter(PrintChanged == ChangePrinter::DotCfgVerbose),
|
2456 |
| - Verify(DebugLogging), VerifyEach(VerifyEach) {} |
| 2544 | + Verify(DebugLogging), DroppedStats(DroppedVarStats), |
| 2545 | + VerifyEach(VerifyEach) {} |
2457 | 2546 |
|
2458 | 2547 | PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
|
2459 | 2548 | nullptr;
|
@@ -2528,6 +2617,7 @@ void StandardInstrumentations::registerCallbacks(
|
2528 | 2617 | WebsiteChangeReporter.registerCallbacks(PIC);
|
2529 | 2618 | ChangeTester.registerCallbacks(PIC);
|
2530 | 2619 | PrintCrashIR.registerCallbacks(PIC);
|
| 2620 | + DroppedStats.registerCallbacks(PIC); |
2531 | 2621 | if (MAM)
|
2532 | 2622 | PreservedCFGChecker.registerCallbacks(PIC, *MAM);
|
2533 | 2623 |
|
|
0 commit comments