[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:
parent
a1e2c65663
commit
0e24179797
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
33
llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll
Normal file
33
llvm/test/CodeGen/Generic/selectiondag-dump-filter.ll
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user