From 0e24179797faf5d309fcc5024131c2293accff26 Mon Sep 17 00:00:00 2001 From: Min-Yih Hsu Date: Mon, 20 Nov 2023 14:00:47 -0800 Subject: [PATCH] [SelectionDAG] Add support to filter SelectionDAG dumps during ISel by function names (#72696) `-debug-only=isel-dump` is the new debug type for printing SelectionDAG after each ISel phase. This can be furthered filter by `-filter-print-funcs=`. Note that the existing `-debug-only=isel` will take precedence over the new behavior and print SelectionDAG dumps of every single function regardless of `-filter-print-funcs`'s values. --- llvm/docs/CodeGenerator.rst | 6 + llvm/docs/ReleaseNotes.rst | 8 ++ llvm/include/llvm/CodeGen/SelectionDAGISel.h | 7 ++ .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 108 +++++++++++------- .../Generic/selectiondag-dump-filter.ll | 33 ++++++ 5 files changed, 119 insertions(+), 43 deletions(-) create mode 100644 llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll diff --git a/llvm/docs/CodeGenerator.rst b/llvm/docs/CodeGenerator.rst index 5fb66c78b3f50..70e4b7eef9599 100644 --- a/llvm/docs/CodeGenerator.rst +++ b/llvm/docs/CodeGenerator.rst @@ -857,6 +857,12 @@ SelectionDAG-based instruction selection consists of the following steps: After all of these steps are complete, the SelectionDAG is destroyed and the rest of the code generation passes are run. +One of the most common ways to debug these steps is using ``-debug-only=isel``, +which prints out the DAG, along with other information like debug info, +after each of these steps. Alternatively, ``-debug-only=isel-dump`` shows only +the DAG dumps, but the results can be filtered by function names using +``-filter-print-funcs=``. + One great way to visualize what is going on here is to take advantage of a few LLC command line options. The following options pop up a window displaying the SelectionDAG at specific times (if you only get errors printed to the console diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index eccac66588072..5804a67e9eb4a 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -201,6 +201,14 @@ Changes to the C API Changes to the CodeGen infrastructure ------------------------------------- +* A new debug type ``isel-dump`` is added to show only the SelectionDAG dumps + after each ISel phase (i.e. ``-debug-only=isel-dump``). This new debug type + can be filtered by function names using ``-filter-print-funcs=``, + the same flag used to filter IR dumps after each Pass. Note that the existing + ``-debug-only=isel`` will take precedence over the new behavior and + print SelectionDAG dumps of every single function regardless of + ``-filter-print-funcs``'s values. + * ``PrologEpilogInserter`` no longer supports register scavenging during forwards frame index elimination. Targets should use backwards frame index elimination instead. diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 884fdfadfcbef..ffeb4959ba7d0 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -61,6 +61,13 @@ class SelectionDAGISel : public MachineFunctionPass { /// Used to report things like combines and FastISel failures. std::unique_ptr ORE; + /// True if the function currently processing is in the function printing list + /// (i.e. `-filter-print-funcs`). + /// This is primarily used by ISEL_DUMP, which spans in multiple member + /// functions. Storing the filter result here so that we only need to do the + /// filtering once. + bool MatchFilterFuncName = false; + explicit SelectionDAGISel(char &ID, TargetMachine &tm, CodeGenOptLevel OL = CodeGenOptLevel::Default); ~SelectionDAGISel() override; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 0a8afa782f1ca..767503dc025a7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -78,6 +78,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/Statepoint.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" @@ -113,6 +114,7 @@ using namespace llvm; #define DEBUG_TYPE "isel" +#define ISEL_DUMP_DEBUG_TYPE DEBUG_TYPE "-dump" STATISTIC(NumFastIselFailures, "Number of instructions fast isel failed on"); STATISTIC(NumFastIselSuccess, "Number of instructions fast isel selected"); @@ -180,6 +182,19 @@ static const bool ViewDAGCombine1 = false, ViewLegalizeTypesDAGs = false, ViewSchedDAGs = false, ViewSUnitDAGs = false; #endif +#ifndef NDEBUG +#define ISEL_DUMP(X) \ + do { \ + if (llvm::DebugFlag && \ + (isCurrentDebugType(DEBUG_TYPE) || \ + (isCurrentDebugType(ISEL_DUMP_DEBUG_TYPE) && MatchFilterFuncName))) { \ + X; \ + } \ + } while (false) +#else +#define ISEL_DUMP(X) do { } while (false) +#endif + //===---------------------------------------------------------------------===// /// /// RegisterScheduler class - Track the registration of instruction schedulers. @@ -403,6 +418,13 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { const Function &Fn = mf.getFunction(); MF = &mf; +#ifndef NDEBUG + StringRef FuncName = Fn.getName(); + MatchFilterFuncName = isFunctionInPrintList(FuncName); +#else + (void)MatchFilterFuncName; +#endif + // Decide what flavour of variable location debug-info will be used, before // we change the optimisation level. bool InstrRef = mf.shouldUseDebugInstrRef(); @@ -436,7 +458,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { if (isAssignmentTrackingEnabled(*Fn.getParent())) FnVarLocs = getAnalysis().getResults(); - LLVM_DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); + ISEL_DUMP(dbgs() << "\n\n\n=== " << FuncName << "\n"); UniformityInfo *UA = nullptr; if (auto *UAPass = getAnalysisIfAvailable()) @@ -668,8 +690,8 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // at this point. FuncInfo->clear(); - LLVM_DEBUG(dbgs() << "*** MachineFunction at end of ISel ***\n"); - LLVM_DEBUG(MF->print(dbgs())); + ISEL_DUMP(dbgs() << "*** MachineFunction at end of ISel ***\n"); + ISEL_DUMP(MF->print(dbgs())); return true; } @@ -777,10 +799,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { BlockName = (MF->getName() + ":" + FuncInfo->MBB->getBasicBlock()->getName()).str(); } - LLVM_DEBUG(dbgs() << "\nInitial selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nInitial selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -797,10 +819,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(BeforeLegalizeTypes, AA, OptLevel); } - LLVM_DEBUG(dbgs() << "\nOptimized lowered selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nOptimized lowered selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -819,10 +841,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { Changed = CurDAG->LegalizeTypes(); } - LLVM_DEBUG(dbgs() << "\nType-legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nType-legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -843,10 +865,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(AfterLegalizeTypes, AA, OptLevel); } - LLVM_DEBUG(dbgs() << "\nOptimized type-legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nOptimized type-legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -861,10 +883,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { } if (Changed) { - LLVM_DEBUG(dbgs() << "\nVector-legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nVector-legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -877,10 +899,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->LegalizeTypes(); } - LLVM_DEBUG(dbgs() << "\nVector/type-legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nVector/type-legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -897,10 +919,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(AfterLegalizeVectorOps, AA, OptLevel); } - LLVM_DEBUG(dbgs() << "\nOptimized vector-legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nOptimized vector-legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -917,10 +939,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Legalize(); } - LLVM_DEBUG(dbgs() << "\nLegalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nLegalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -937,10 +959,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { CurDAG->Combine(AfterLegalizeDAG, AA, OptLevel); } - LLVM_DEBUG(dbgs() << "\nOptimized legalized selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nOptimized legalized selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); #ifndef NDEBUG if (TTI.hasBranchDivergence()) @@ -961,10 +983,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { DoInstructionSelection(); } - LLVM_DEBUG(dbgs() << "\nSelected selection DAG: " - << printMBBReference(*FuncInfo->MBB) << " '" << BlockName - << "'\n"; - CurDAG->dump()); + ISEL_DUMP(dbgs() << "\nSelected selection DAG: " + << printMBBReference(*FuncInfo->MBB) << " '" << BlockName + << "'\n"; + CurDAG->dump()); if (ViewSchedDAGs && MatchFilterBB) CurDAG->viewGraph("scheduler input for " + BlockName); diff --git a/llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll b/llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll new file mode 100644 index 0000000000000..fb621610ccc4f --- /dev/null +++ b/llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll @@ -0,0 +1,33 @@ +; RUN: llc -debug-only=isel-dump -filter-print-funcs=foo < %s 2>&1 | FileCheck %s --check-prefix=FOO +; RUN: llc -debug-only=isel-dump -filter-print-funcs=bar < %s 2>&1 | FileCheck %s --check-prefix=BAR +; RUN: llc -debug-only=isel-dump -filter-print-funcs=foo,zap < %s 2>&1 | FileCheck %s --check-prefixes=FOO,ZAP +; Make sure the original -debug-only=isel still works. +; RUN: llc -debug-only=isel < %s 2>&1 | FileCheck %s --check-prefixes=FOO,BAR,ZAP +; REQUIRES: asserts + +; FOO: === foo +; BAR-NOT: === foo +; ZAP-NOT: === foo +; FOO: # Machine code for function foo +define i32 @foo(i32 %a, i32 %b) { + %r = add i32 %a, %b + ret i32 %r +} + +; BAR: === bar +; FOO-NOT: === bar +; ZAP-NOT: === bar +; BAR: # Machine code for function bar +define i32 @bar(i32 %a, i32 %b) { + %r = mul i32 %a, %b + ret i32 %r +} + +; ZAP: === zap +; FOO-NOT: === zap +; BAR-NOT: === zap +; ZAP: # Machine code for function zap +define i32 @zap(i32 %a, i32 %b) { + %r = sub i32 %a, %b + ret i32 %r +}