[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=<function names>`.
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.
This commit is contained in:
Min-Yih Hsu 2023-11-20 14:00:47 -08:00 committed by GitHub
parent a1e2c65663
commit 0e24179797
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 43 deletions

View File

@ -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 After all of these steps are complete, the SelectionDAG is destroyed and the
rest of the code generation passes are run. 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=<function names>``.
One great way to visualize what is going on here is to take advantage of a few 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 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 SelectionDAG at specific times (if you only get errors printed to the console

View File

@ -201,6 +201,14 @@ Changes to the C API
Changes to the CodeGen infrastructure 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=<function names>``,
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 * ``PrologEpilogInserter`` no longer supports register scavenging
during forwards frame index elimination. Targets should use during forwards frame index elimination. Targets should use
backwards frame index elimination instead. backwards frame index elimination instead.

View File

@ -61,6 +61,13 @@ public:
/// Used to report things like combines and FastISel failures. /// Used to report things like combines and FastISel failures.
std::unique_ptr<OptimizationRemarkEmitter> ORE; std::unique_ptr<OptimizationRemarkEmitter> 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, explicit SelectionDAGISel(char &ID, TargetMachine &tm,
CodeGenOptLevel OL = CodeGenOptLevel::Default); CodeGenOptLevel OL = CodeGenOptLevel::Default);
~SelectionDAGISel() override; ~SelectionDAGISel() override;

View File

@ -78,6 +78,7 @@
#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/Metadata.h" #include "llvm/IR/Metadata.h"
#include "llvm/IR/PrintPasses.h"
#include "llvm/IR/Statepoint.h" #include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h" #include "llvm/IR/Type.h"
#include "llvm/IR/User.h" #include "llvm/IR/User.h"
@ -113,6 +114,7 @@
using namespace llvm; using namespace llvm;
#define DEBUG_TYPE "isel" #define DEBUG_TYPE "isel"
#define ISEL_DUMP_DEBUG_TYPE DEBUG_TYPE "-dump"
STATISTIC(NumFastIselFailures, "Number of instructions fast isel failed on"); STATISTIC(NumFastIselFailures, "Number of instructions fast isel failed on");
STATISTIC(NumFastIselSuccess, "Number of instructions fast isel selected"); STATISTIC(NumFastIselSuccess, "Number of instructions fast isel selected");
@ -180,6 +182,19 @@ static const bool ViewDAGCombine1 = false, ViewLegalizeTypesDAGs = false,
ViewSchedDAGs = false, ViewSUnitDAGs = false; ViewSchedDAGs = false, ViewSUnitDAGs = false;
#endif #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. /// RegisterScheduler class - Track the registration of instruction schedulers.
@ -403,6 +418,13 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
const Function &Fn = mf.getFunction(); const Function &Fn = mf.getFunction();
MF = &mf; 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 // Decide what flavour of variable location debug-info will be used, before
// we change the optimisation level. // we change the optimisation level.
bool InstrRef = mf.shouldUseDebugInstrRef(); bool InstrRef = mf.shouldUseDebugInstrRef();
@ -436,7 +458,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
if (isAssignmentTrackingEnabled(*Fn.getParent())) if (isAssignmentTrackingEnabled(*Fn.getParent()))
FnVarLocs = getAnalysis<AssignmentTrackingAnalysis>().getResults(); FnVarLocs = getAnalysis<AssignmentTrackingAnalysis>().getResults();
LLVM_DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); ISEL_DUMP(dbgs() << "\n\n\n=== " << FuncName << "\n");
UniformityInfo *UA = nullptr; UniformityInfo *UA = nullptr;
if (auto *UAPass = getAnalysisIfAvailable<UniformityInfoWrapperPass>()) if (auto *UAPass = getAnalysisIfAvailable<UniformityInfoWrapperPass>())
@ -668,8 +690,8 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
// at this point. // at this point.
FuncInfo->clear(); FuncInfo->clear();
LLVM_DEBUG(dbgs() << "*** MachineFunction at end of ISel ***\n"); ISEL_DUMP(dbgs() << "*** MachineFunction at end of ISel ***\n");
LLVM_DEBUG(MF->print(dbgs())); ISEL_DUMP(MF->print(dbgs()));
return true; return true;
} }
@ -777,10 +799,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
BlockName = BlockName =
(MF->getName() + ":" + FuncInfo->MBB->getBasicBlock()->getName()).str(); (MF->getName() + ":" + FuncInfo->MBB->getBasicBlock()->getName()).str();
} }
LLVM_DEBUG(dbgs() << "\nInitial selection DAG: " ISEL_DUMP(dbgs() << "\nInitial selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -797,10 +819,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->Combine(BeforeLegalizeTypes, AA, OptLevel); CurDAG->Combine(BeforeLegalizeTypes, AA, OptLevel);
} }
LLVM_DEBUG(dbgs() << "\nOptimized lowered selection DAG: " ISEL_DUMP(dbgs() << "\nOptimized lowered selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -819,10 +841,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
Changed = CurDAG->LegalizeTypes(); Changed = CurDAG->LegalizeTypes();
} }
LLVM_DEBUG(dbgs() << "\nType-legalized selection DAG: " ISEL_DUMP(dbgs() << "\nType-legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -843,10 +865,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->Combine(AfterLegalizeTypes, AA, OptLevel); CurDAG->Combine(AfterLegalizeTypes, AA, OptLevel);
} }
LLVM_DEBUG(dbgs() << "\nOptimized type-legalized selection DAG: " ISEL_DUMP(dbgs() << "\nOptimized type-legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -861,10 +883,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
} }
if (Changed) { if (Changed) {
LLVM_DEBUG(dbgs() << "\nVector-legalized selection DAG: " ISEL_DUMP(dbgs() << "\nVector-legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -877,10 +899,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->LegalizeTypes(); CurDAG->LegalizeTypes();
} }
LLVM_DEBUG(dbgs() << "\nVector/type-legalized selection DAG: " ISEL_DUMP(dbgs() << "\nVector/type-legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -897,10 +919,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->Combine(AfterLegalizeVectorOps, AA, OptLevel); CurDAG->Combine(AfterLegalizeVectorOps, AA, OptLevel);
} }
LLVM_DEBUG(dbgs() << "\nOptimized vector-legalized selection DAG: " ISEL_DUMP(dbgs() << "\nOptimized vector-legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -917,10 +939,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->Legalize(); CurDAG->Legalize();
} }
LLVM_DEBUG(dbgs() << "\nLegalized selection DAG: " ISEL_DUMP(dbgs() << "\nLegalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -937,10 +959,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
CurDAG->Combine(AfterLegalizeDAG, AA, OptLevel); CurDAG->Combine(AfterLegalizeDAG, AA, OptLevel);
} }
LLVM_DEBUG(dbgs() << "\nOptimized legalized selection DAG: " ISEL_DUMP(dbgs() << "\nOptimized legalized selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
#ifndef NDEBUG #ifndef NDEBUG
if (TTI.hasBranchDivergence()) if (TTI.hasBranchDivergence())
@ -961,10 +983,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
DoInstructionSelection(); DoInstructionSelection();
} }
LLVM_DEBUG(dbgs() << "\nSelected selection DAG: " ISEL_DUMP(dbgs() << "\nSelected selection DAG: "
<< printMBBReference(*FuncInfo->MBB) << " '" << BlockName << printMBBReference(*FuncInfo->MBB) << " '" << BlockName
<< "'\n"; << "'\n";
CurDAG->dump()); CurDAG->dump());
if (ViewSchedDAGs && MatchFilterBB) if (ViewSchedDAGs && MatchFilterBB)
CurDAG->viewGraph("scheduler input for " + BlockName); CurDAG->viewGraph("scheduler input for " + BlockName);

View File

@ -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
}