Skip to content

Commit 117b53a

Browse files
authored
[AsmPrinter] Reduce AsmPrinterHandlers virt. fn calls (#96785)
Currently, an AsmPrinterHandler has several methods that allow to dynamically hook in unwind or debug info emission, e.g. at begin/end of every function or instruction. The class hierarchy and the actually overridden functions are as follows: (SymSz=setSymbolSize, mFE=markFunctionEnd, BBS=BasicBlockSection, FL=Funclet; b=beginX, e=endX) SymSz Mod Fn mFE BBS FL Inst AsmPrinterHandler - - - - - - - ` PseudoProbeHandler - - - - - - - ` WinCFGuard - e e - - - - ` EHStreamer - - - - - - - ` DwarfCFIException - e be - be - - ` ARMException - - be e - - - ` AIXException - - e - - - - ` WinException - e be e - be - ` WasmException - e be - - - - ` DebugHandlerBase - b be - be - be ` BTFDebug - e - - - - b ` CodeViewDebug - be - - - - b ` DWARFDebug yes be - - - - b Doing virtual function calls per instruction is costly and useless when the called function does nothing. This commit performs the following clean-up/improvements: - PseudoProbeHandler is no longer an AsmPrinterHandler -- it used nothing of its functionality to hook in at the possible points. This avoids virtual function calls when a pseudo probe printer is present. - DebugHandlerBase is no longer an AsmPrinterHandler, but a separate base class. DebugHandlerBase is the only remaining "hook" for begin/end instruction and setSymbolSize (only used by DWARFDebug). begin/end for function and basic block sections are never overriden and therefore are no longer virtual. (Originally I intended there to be only one debug handler, but BPF as the only target supports two at the same time: DWARF and BTF.) - AsmPrinterHandler no longer has begin/end instruction and setSymbolSize hooks -- these were only used by DebugHandlerBase. This avoid iterating over handlers in every instruction. AsmPrinterHandler Mod Fn mFE BBS FL ` WinCFGuard e e - - - ` EHStreamer - - - - - ` DwarfCFIException e be - be - ` ARMException - be e - - ` AIXException - e - - - ` WinException e be e - be ` WasmException e be - - - SymSz Mod Fn BBS Inst DebugHandlerBase - b be be be ` BTFDebug - e b ` CodeViewDebug - be b ` DWARFDebug yes be b PseudoProbeHandler (no shared methods) To continue allowing external users (e.g., Julia) to hook in at every instruction, a new method addDebugHandler is exposed. This results in a performance improvement, especially in the -O0 -g0 case with unwind information (e.g., JIT baseline).
1 parent 3c64a98 commit 117b53a

File tree

13 files changed

+157
-97
lines changed

13 files changed

+157
-97
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/SmallVector.h"
2121
#include "llvm/BinaryFormat/Dwarf.h"
2222
#include "llvm/CodeGen/AsmPrinterHandler.h"
23+
#include "llvm/CodeGen/DebugHandlerBase.h"
2324
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
2425
#include "llvm/CodeGen/MachineFunctionPass.h"
2526
#include "llvm/CodeGen/StackMaps.h"
@@ -145,14 +146,14 @@ class AsmPrinter : public MachineFunctionPass {
145146

146147
/// struct HandlerInfo and Handlers permit users or target extended
147148
/// AsmPrinter to add their own handlers.
148-
struct HandlerInfo {
149-
std::unique_ptr<AsmPrinterHandler> Handler;
149+
template <class H> struct HandlerInfo {
150+
std::unique_ptr<H> Handler;
150151
StringRef TimerName;
151152
StringRef TimerDescription;
152153
StringRef TimerGroupName;
153154
StringRef TimerGroupDescription;
154155

155-
HandlerInfo(std::unique_ptr<AsmPrinterHandler> Handler, StringRef TimerName,
156+
HandlerInfo(std::unique_ptr<H> Handler, StringRef TimerName,
156157
StringRef TimerDescription, StringRef TimerGroupName,
157158
StringRef TimerGroupDescription)
158159
: Handler(std::move(Handler)), TimerName(TimerName),
@@ -205,9 +206,13 @@ class AsmPrinter : public MachineFunctionPass {
205206

206207
/// A vector of all debug/EH info emitters we should use. This vector
207208
/// maintains ownership of the emitters.
208-
std::vector<HandlerInfo> Handlers;
209+
SmallVector<HandlerInfo<AsmPrinterHandler>, 2> Handlers;
209210
size_t NumUserHandlers = 0;
210211

212+
/// Debuginfo handler. Protected so that targets can add their own.
213+
SmallVector<HandlerInfo<DebugHandlerBase>, 1> DebugHandlers;
214+
size_t NumUserDebugHandlers = 0;
215+
211216
StackMaps SM;
212217

213218
private:
@@ -222,7 +227,7 @@ class AsmPrinter : public MachineFunctionPass {
222227

223228
/// A handler that supports pseudo probe emission with embedded inline
224229
/// context.
225-
PseudoProbeHandler *PP = nullptr;
230+
std::unique_ptr<PseudoProbeHandler> PP;
226231

227232
/// CFISection type the module needs i.e. either .eh_frame or .debug_frame.
228233
CFISection ModuleCFISection = CFISection::None;
@@ -531,11 +536,16 @@ class AsmPrinter : public MachineFunctionPass {
531536
// Overridable Hooks
532537
//===------------------------------------------------------------------===//
533538

534-
void addAsmPrinterHandler(HandlerInfo Handler) {
539+
void addAsmPrinterHandler(HandlerInfo<AsmPrinterHandler> Handler) {
535540
Handlers.insert(Handlers.begin(), std::move(Handler));
536541
NumUserHandlers++;
537542
}
538543

544+
void addDebugHandler(HandlerInfo<DebugHandlerBase> Handler) {
545+
DebugHandlers.insert(DebugHandlers.begin(), std::move(Handler));
546+
NumUserDebugHandlers++;
547+
}
548+
539549
// Targets can, or in the case of EmitInstruction, must implement these to
540550
// customize output.
541551

llvm/include/llvm/CodeGen/AsmPrinterHandler.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ class AsmPrinterHandler {
3434
public:
3535
virtual ~AsmPrinterHandler();
3636

37-
/// For symbols that have a size designated (e.g. common symbols),
38-
/// this tracks that size.
39-
virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0;
40-
4137
virtual void beginModule(Module *M) {}
4238

4339
/// Emit all sections that should come after the content.
@@ -72,12 +68,6 @@ class AsmPrinterHandler {
7268
virtual void beginFunclet(const MachineBasicBlock &MBB,
7369
MCSymbol *Sym = nullptr) {}
7470
virtual void endFunclet() {}
75-
76-
/// Process beginning of an instruction.
77-
virtual void beginInstruction(const MachineInstr *MI) = 0;
78-
79-
/// Process end of an instruction.
80-
virtual void endInstruction() = 0;
8171
};
8272

8373
} // End of namespace llvm

llvm/include/llvm/CodeGen/DebugHandlerBase.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,14 @@ struct DbgVariableLocation {
5050

5151
/// Base class for debug information backends. Common functionality related to
5252
/// tracking which variables and scopes are alive at a given PC live here.
53-
class DebugHandlerBase : public AsmPrinterHandler {
53+
class DebugHandlerBase {
5454
protected:
5555
DebugHandlerBase(AsmPrinter *A);
5656

57+
public:
58+
virtual ~DebugHandlerBase();
59+
60+
protected:
5761
/// Target of debug info emission.
5862
AsmPrinter *Asm = nullptr;
5963

@@ -116,18 +120,22 @@ class DebugHandlerBase : public AsmPrinterHandler {
116120
private:
117121
InstructionOrdering InstOrdering;
118122

119-
// AsmPrinterHandler overrides.
120123
public:
121-
void beginModule(Module *M) override;
124+
/// For symbols that have a size designated (e.g. common symbols),
125+
/// this tracks that size. Only used by DWARF.
126+
virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) {}
127+
128+
virtual void beginModule(Module *M);
129+
virtual void endModule() = 0;
122130

123-
void beginInstruction(const MachineInstr *MI) override;
124-
void endInstruction() override;
131+
virtual void beginInstruction(const MachineInstr *MI);
132+
virtual void endInstruction();
125133

126-
void beginFunction(const MachineFunction *MF) override;
127-
void endFunction(const MachineFunction *MF) override;
134+
void beginFunction(const MachineFunction *MF);
135+
void endFunction(const MachineFunction *MF);
128136

129-
void beginBasicBlockSection(const MachineBasicBlock &MBB) override;
130-
void endBasicBlockSection(const MachineBasicBlock &MBB) override;
137+
void beginBasicBlockSection(const MachineBasicBlock &MBB);
138+
void endBasicBlockSection(const MachineBasicBlock &MBB);
131139

132140
/// Return Label preceding the instruction.
133141
MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,6 @@ const char CFGuardName[] = "Control Flow Guard";
166166
const char CFGuardDescription[] = "Control Flow Guard";
167167
const char CodeViewLineTablesGroupName[] = "linetables";
168168
const char CodeViewLineTablesGroupDescription[] = "CodeView Line Tables";
169-
const char PPTimerName[] = "emit";
170-
const char PPTimerDescription[] = "Pseudo Probe Emission";
171-
const char PPGroupName[] = "pseudo probe";
172-
const char PPGroupDescription[] = "Pseudo Probe Emission";
173169

174170
STATISTIC(EmittedInsts, "Number of machine instrs printed");
175171

@@ -555,27 +551,24 @@ bool AsmPrinter::doInitialization(Module &M) {
555551
if (MAI->doesSupportDebugInformation()) {
556552
bool EmitCodeView = M.getCodeViewFlag();
557553
if (EmitCodeView && TM.getTargetTriple().isOSWindows()) {
558-
Handlers.emplace_back(std::make_unique<CodeViewDebug>(this),
559-
DbgTimerName, DbgTimerDescription,
560-
CodeViewLineTablesGroupName,
561-
CodeViewLineTablesGroupDescription);
554+
DebugHandlers.emplace_back(std::make_unique<CodeViewDebug>(this),
555+
DbgTimerName, DbgTimerDescription,
556+
CodeViewLineTablesGroupName,
557+
CodeViewLineTablesGroupDescription);
562558
}
563559
if (!EmitCodeView || M.getDwarfVersion()) {
564560
assert(MMI && "MMI could not be nullptr here!");
565561
if (MMI->hasDebugInfo()) {
566562
DD = new DwarfDebug(this);
567-
Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName,
568-
DbgTimerDescription, DWARFGroupName,
569-
DWARFGroupDescription);
563+
DebugHandlers.emplace_back(std::unique_ptr<DwarfDebug>(DD),
564+
DbgTimerName, DbgTimerDescription,
565+
DWARFGroupName, DWARFGroupDescription);
570566
}
571567
}
572568
}
573569

574-
if (M.getNamedMetadata(PseudoProbeDescMetadataName)) {
575-
PP = new PseudoProbeHandler(this);
576-
Handlers.emplace_back(std::unique_ptr<PseudoProbeHandler>(PP), PPTimerName,
577-
PPTimerDescription, PPGroupName, PPGroupDescription);
578-
}
570+
if (M.getNamedMetadata(PseudoProbeDescMetadataName))
571+
PP = std::make_unique<PseudoProbeHandler>(this);
579572

580573
switch (MAI->getExceptionHandlingType()) {
581574
case ExceptionHandling::None:
@@ -642,7 +635,12 @@ bool AsmPrinter::doInitialization(Module &M) {
642635
CFGuardDescription, DWARFGroupName,
643636
DWARFGroupDescription);
644637

645-
for (const HandlerInfo &HI : Handlers) {
638+
for (const auto &HI : DebugHandlers) {
639+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
640+
HI.TimerGroupDescription, TimePassesIsEnabled);
641+
HI.Handler->beginModule(&M);
642+
}
643+
for (const auto &HI : Handlers) {
646644
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
647645
HI.TimerGroupDescription, TimePassesIsEnabled);
648646
HI.Handler->beginModule(&M);
@@ -793,10 +791,9 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
793791
// sections and expected to be contiguous (e.g. ObjC metadata).
794792
const Align Alignment = getGVAlignment(GV, DL);
795793

796-
for (const HandlerInfo &HI : Handlers) {
797-
NamedRegionTimer T(HI.TimerName, HI.TimerDescription,
798-
HI.TimerGroupName, HI.TimerGroupDescription,
799-
TimePassesIsEnabled);
794+
for (auto &HI : DebugHandlers) {
795+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
796+
HI.TimerGroupDescription, TimePassesIsEnabled);
800797
HI.Handler->setSymbolSize(GVSym, Size);
801798
}
802799

@@ -1069,12 +1066,18 @@ void AsmPrinter::emitFunctionHeader() {
10691066
}
10701067

10711068
// Emit pre-function debug and/or EH information.
1072-
for (const HandlerInfo &HI : Handlers) {
1069+
for (const auto &HI : DebugHandlers) {
10731070
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
10741071
HI.TimerGroupDescription, TimePassesIsEnabled);
10751072
HI.Handler->beginFunction(MF);
1073+
HI.Handler->beginBasicBlockSection(MF->front());
10761074
}
1077-
for (const HandlerInfo &HI : Handlers) {
1075+
for (const auto &HI : Handlers) {
1076+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
1077+
HI.TimerGroupDescription, TimePassesIsEnabled);
1078+
HI.Handler->beginFunction(MF);
1079+
}
1080+
for (const auto &HI : Handlers) {
10781081
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
10791082
HI.TimerGroupDescription, TimePassesIsEnabled);
10801083
HI.Handler->beginBasicBlockSection(MF->front());
@@ -1773,7 +1776,7 @@ void AsmPrinter::emitFunctionBody() {
17731776
if (MDNode *MD = MI.getPCSections())
17741777
emitPCSectionsLabel(*MF, *MD);
17751778

1776-
for (const HandlerInfo &HI : Handlers) {
1779+
for (const auto &HI : DebugHandlers) {
17771780
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
17781781
HI.TimerGroupDescription, TimePassesIsEnabled);
17791782
HI.Handler->beginInstruction(&MI);
@@ -1871,7 +1874,7 @@ void AsmPrinter::emitFunctionBody() {
18711874
if (MCSymbol *S = MI.getPostInstrSymbol())
18721875
OutStreamer->emitLabel(S);
18731876

1874-
for (const HandlerInfo &HI : Handlers) {
1877+
for (const auto &HI : DebugHandlers) {
18751878
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
18761879
HI.TimerGroupDescription, TimePassesIsEnabled);
18771880
HI.Handler->endInstruction();
@@ -2006,13 +2009,18 @@ void AsmPrinter::emitFunctionBody() {
20062009
// Call endBasicBlockSection on the last block now, if it wasn't already
20072010
// called.
20082011
if (!MF->back().isEndSection()) {
2009-
for (const HandlerInfo &HI : Handlers) {
2012+
for (const auto &HI : DebugHandlers) {
2013+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
2014+
HI.TimerGroupDescription, TimePassesIsEnabled);
2015+
HI.Handler->endBasicBlockSection(MF->back());
2016+
}
2017+
for (const auto &HI : Handlers) {
20102018
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
20112019
HI.TimerGroupDescription, TimePassesIsEnabled);
20122020
HI.Handler->endBasicBlockSection(MF->back());
20132021
}
20142022
}
2015-
for (const HandlerInfo &HI : Handlers) {
2023+
for (const auto &HI : Handlers) {
20162024
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
20172025
HI.TimerGroupDescription, TimePassesIsEnabled);
20182026
HI.Handler->markFunctionEnd();
@@ -2025,7 +2033,12 @@ void AsmPrinter::emitFunctionBody() {
20252033
emitJumpTableInfo();
20262034

20272035
// Emit post-function debug and/or EH information.
2028-
for (const HandlerInfo &HI : Handlers) {
2036+
for (const auto &HI : DebugHandlers) {
2037+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
2038+
HI.TimerGroupDescription, TimePassesIsEnabled);
2039+
HI.Handler->endFunction(MF);
2040+
}
2041+
for (const auto &HI : Handlers) {
20292042
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
20302043
HI.TimerGroupDescription, TimePassesIsEnabled);
20312044
HI.Handler->endFunction(MF);
@@ -2466,7 +2479,12 @@ bool AsmPrinter::doFinalization(Module &M) {
24662479
emitGlobalIFunc(M, IFunc);
24672480

24682481
// Finalize debug and EH information.
2469-
for (const HandlerInfo &HI : Handlers) {
2482+
for (const auto &HI : DebugHandlers) {
2483+
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
2484+
HI.TimerGroupDescription, TimePassesIsEnabled);
2485+
HI.Handler->endModule();
2486+
}
2487+
for (const auto &HI : Handlers) {
24702488
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
24712489
HI.TimerGroupDescription, TimePassesIsEnabled);
24722490
HI.Handler->endModule();
@@ -2476,6 +2494,8 @@ bool AsmPrinter::doFinalization(Module &M) {
24762494
// keeping all the user-added handlers alive until the AsmPrinter is
24772495
// destroyed.
24782496
Handlers.erase(Handlers.begin() + NumUserHandlers, Handlers.end());
2497+
DebugHandlers.erase(DebugHandlers.begin() + NumUserDebugHandlers,
2498+
DebugHandlers.end());
24792499
DD = nullptr;
24802500

24812501
// If the target wants to know about weak references, print them all.
@@ -3990,7 +4010,7 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,
39904010
void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
39914011
// End the previous funclet and start a new one.
39924012
if (MBB.isEHFuncletEntry()) {
3993-
for (const HandlerInfo &HI : Handlers) {
4013+
for (const auto &HI : Handlers) {
39944014
HI.Handler->endFunclet();
39954015
HI.Handler->beginFunclet(MBB);
39964016
}
@@ -4062,17 +4082,23 @@ void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
40624082
// With BB sections, each basic block must handle CFI information on its own
40634083
// if it begins a section (Entry block call is handled separately, next to
40644084
// beginFunction).
4065-
if (MBB.isBeginSection() && !MBB.isEntryBlock())
4066-
for (const HandlerInfo &HI : Handlers)
4085+
if (MBB.isBeginSection() && !MBB.isEntryBlock()) {
4086+
for (const auto &HI : DebugHandlers)
4087+
HI.Handler->beginBasicBlockSection(MBB);
4088+
for (const auto &HI : Handlers)
40674089
HI.Handler->beginBasicBlockSection(MBB);
4090+
}
40684091
}
40694092

40704093
void AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
40714094
// Check if CFI information needs to be updated for this MBB with basic block
40724095
// sections.
4073-
if (MBB.isEndSection())
4074-
for (const HandlerInfo &HI : Handlers)
4096+
if (MBB.isEndSection()) {
4097+
for (const auto &HI : DebugHandlers)
4098+
HI.Handler->endBasicBlockSection(MBB);
4099+
for (const auto &HI : Handlers)
40754100
HI.Handler->endBasicBlockSection(MBB);
4101+
}
40764102
}
40774103

40784104
void AsmPrinter::emitVisibility(MCSymbol *Sym, unsigned Visibility,

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
517517

518518
void beginModule(Module *M) override;
519519

520-
void setSymbolSize(const MCSymbol *, uint64_t) override {}
521-
522520
/// Emit the COFF section that holds the line table information.
523521
void endModule() override;
524522

llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ DbgVariableLocation::extractFromMachineInstruction(
100100

101101
DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}
102102

103+
DebugHandlerBase::~DebugHandlerBase() = default;
104+
103105
void DebugHandlerBase::beginModule(Module *M) {
104106
if (M->debug_compile_units().empty())
105107
Asm = nullptr;

llvm/lib/CodeGen/AsmPrinter/EHStreamer.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,6 @@ class LLVM_LIBRARY_VISIBILITY EHStreamer : public AsmPrinterHandler {
150150
EHStreamer(AsmPrinter *A);
151151
~EHStreamer() override;
152152

153-
// Unused.
154-
void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
155-
void beginInstruction(const MachineInstr *MI) override {}
156-
void endInstruction() override {}
157-
158153
/// Return `true' if this is a call to a function marked `nounwind'. Return
159154
/// `false' otherwise.
160155
static bool callToNoUnwindFunction(const MachineInstr *MI);

llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
using namespace llvm;
2222

23-
PseudoProbeHandler::~PseudoProbeHandler() = default;
24-
2523
void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index,
2624
uint64_t Type, uint64_t Attr,
2725
const DILocation *DebugLoc) {

0 commit comments

Comments
 (0)