|
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/IntrinsicInst.h" |
28 | 29 | #include "llvm/IR/Module.h"
|
29 | 30 | #include "llvm/IR/PassInstrumentation.h"
|
30 | 31 | #include "llvm/IR/PassManager.h"
|
@@ -139,6 +140,11 @@ static cl::opt<std::string> IRDumpDirectory(
|
139 | 140 | "files in this directory rather than written to stderr"),
|
140 | 141 | cl::Hidden, cl::value_desc("filename"));
|
141 | 142 |
|
| 143 | +static cl::opt<bool> |
| 144 | + DroppedVarStats("dropped-variable-stats", cl::Hidden, |
| 145 | + cl::desc("Dump dropped debug variables stats"), |
| 146 | + cl::init(false)); |
| 147 | + |
142 | 148 | template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {
|
143 | 149 | const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);
|
144 | 150 | return IRPtr ? *IRPtr : nullptr;
|
@@ -2441,6 +2447,84 @@ void DotCfgChangeReporter::registerCallbacks(
|
2441 | 2447 | }
|
2442 | 2448 | }
|
2443 | 2449 |
|
| 2450 | +void DroppedVariableStats::registerCallbacks( |
| 2451 | + PassInstrumentationCallbacks &PIC) { |
| 2452 | + if (!DroppedVarStats) |
| 2453 | + return; |
| 2454 | + |
| 2455 | + PIC.registerBeforeNonSkippedPassCallback( |
| 2456 | + [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); }); |
| 2457 | + PIC.registerAfterPassCallback( |
| 2458 | + [this](StringRef P, Any IR, const PreservedAnalyses &PA) { |
| 2459 | + return this->runAfterPass(P, IR, PA); |
| 2460 | + }); |
| 2461 | +} |
| 2462 | + |
| 2463 | +void DroppedVariableStats::runBeforePass(StringRef PassID, Any IR) { |
| 2464 | + DebugVariablesBefore.push_back( |
| 2465 | + std::make_pair(llvm::DenseSet<VarID>(), PassID.str())); |
| 2466 | + DebugVariablesAfter.push_back( |
| 2467 | + std::make_pair(llvm::DenseSet<VarID>(), PassID.str())); |
| 2468 | + if (auto *M = unwrapIR<Module>(IR)) |
| 2469 | + return this->runOnModule(M, true); |
| 2470 | + if (auto *F = unwrapIR<Function>(IR)) |
| 2471 | + return this->runOnFunction(F, true); |
| 2472 | + return; |
| 2473 | +} |
| 2474 | + |
| 2475 | +void DroppedVariableStats::runOnFunction(const Function *F, bool Before) { |
| 2476 | + auto &DebugVariables = Before ? DebugVariablesBefore : DebugVariablesAfter; |
| 2477 | + for (auto &BB : *F) { |
| 2478 | + for (const Instruction &I : BB) { |
| 2479 | + for (DbgRecord &DR : I.getDbgRecordRange()) { |
| 2480 | + if (auto *Dbg = dyn_cast<DbgVariableRecord>(&DR)) { |
| 2481 | + llvm::StringRef UniqueName = Dbg->getVariable()->getName(); |
| 2482 | + auto DbgLoc = DR.getDebugLoc(); |
| 2483 | + unsigned Line = DbgLoc.getLine(); |
| 2484 | + unsigned Col = DbgLoc->getColumn(); |
| 2485 | + VarID Key(cast<DILocalScope>(DbgLoc.getScope()), UniqueName, Line, |
| 2486 | + Col); |
| 2487 | + DebugVariables.back().first.insert(Key); |
| 2488 | + } |
| 2489 | + } |
| 2490 | + } |
| 2491 | + } |
| 2492 | +} |
| 2493 | + |
| 2494 | +void DroppedVariableStats::runOnModule(const Module *M, bool Before) { |
| 2495 | + for (auto &F : *M) |
| 2496 | + runOnFunction(&F, Before); |
| 2497 | +} |
| 2498 | + |
| 2499 | +void DroppedVariableStats::runAfterPass(StringRef PassID, Any IR, |
| 2500 | + const PreservedAnalyses &PA) { |
| 2501 | + assert(DebugVariablesBefore.back().second == |
| 2502 | + DebugVariablesAfter.back().second); |
| 2503 | + unsigned DroppedCount = 0; |
| 2504 | + std::string PassLevel = ""; |
| 2505 | + std::string FuncOrModName = ""; |
| 2506 | + if (auto *M = unwrapIR<Module>(IR)) { |
| 2507 | + this->runOnModule(M, false); |
| 2508 | + PassLevel = "Module"; |
| 2509 | + FuncOrModName = M->getName(); |
| 2510 | + } else if (auto *F = unwrapIR<Function>(IR)) { |
| 2511 | + this->runOnFunction(F, false); |
| 2512 | + PassLevel = "Function"; |
| 2513 | + FuncOrModName = F->getName(); |
| 2514 | + } else { |
| 2515 | + return; |
| 2516 | + } |
| 2517 | + for (auto Var : DebugVariablesBefore.back().first) |
| 2518 | + if (!DebugVariablesAfter.back().first.contains(Var)) |
| 2519 | + DroppedCount++; |
| 2520 | + if (DroppedCount > 0) |
| 2521 | + llvm::outs() << PassLevel << ", " << PassID << ", " << DroppedCount << ", " |
| 2522 | + << FuncOrModName << "\n"; |
| 2523 | + DebugVariablesBefore.pop_back(); |
| 2524 | + DebugVariablesAfter.pop_back(); |
| 2525 | + return; |
| 2526 | +} |
| 2527 | + |
2444 | 2528 | StandardInstrumentations::StandardInstrumentations(
|
2445 | 2529 | LLVMContext &Context, bool DebugLogging, bool VerifyEach,
|
2446 | 2530 | PrintPassOptions PrintPassOpts)
|
@@ -2528,6 +2612,7 @@ void StandardInstrumentations::registerCallbacks(
|
2528 | 2612 | WebsiteChangeReporter.registerCallbacks(PIC);
|
2529 | 2613 | ChangeTester.registerCallbacks(PIC);
|
2530 | 2614 | PrintCrashIR.registerCallbacks(PIC);
|
| 2615 | + DroppedStats.registerCallbacks(PIC); |
2531 | 2616 | if (MAM)
|
2532 | 2617 | PreservedCFGChecker.registerCallbacks(PIC, *MAM);
|
2533 | 2618 |
|
|
0 commit comments