-
Notifications
You must be signed in to change notification settings - Fork 387
/
OpcodeCounter.cpp
144 lines (129 loc) · 5.64 KB
/
OpcodeCounter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//=============================================================================
// FILE:
// OpcodeCounter.cpp
//
// DESCRIPTION:
// Visits all instructions in a function and counts how many times every
// LLVM IR opcode was used. Prints the output to stderr.
//
// This example demonstrates how to insert your pass at one of the
// predefined extension points, e.g. whenever the vectoriser is run (i.e. via
// `registerVectorizerStartEPCallback` for the new PM).
//
// USAGE:
// 1. New PM
// opt -load-pass-plugin libOpcodeCounter.dylib `\`
// -passes="print<opcode-counter>" `\`
// -disable-output <input-llvm-file>
// 2. Automatically through an optimisation pipeline - new PM
// opt -load-pass-plugin libOpcodeCounter.dylib --passes='default<O1>' `\`
// -disable-output <input-llvm-file>
//
// License: MIT
//=============================================================================
#include "OpcodeCounter.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
using namespace llvm;
// Pretty-prints the result of this analysis
static void printOpcodeCounterResult(llvm::raw_ostream &,
const ResultOpcodeCounter &OC);
//-----------------------------------------------------------------------------
// OpcodeCounter implementation
//-----------------------------------------------------------------------------
llvm::AnalysisKey OpcodeCounter::Key;
OpcodeCounter::Result OpcodeCounter::generateOpcodeMap(llvm::Function &Func) {
OpcodeCounter::Result OpcodeMap;
for (auto &BB : Func) {
for (auto &Inst : BB) {
StringRef Name = Inst.getOpcodeName();
if (OpcodeMap.find(Name) == OpcodeMap.end()) {
OpcodeMap[Inst.getOpcodeName()] = 1;
} else {
OpcodeMap[Inst.getOpcodeName()]++;
}
}
}
return OpcodeMap;
}
OpcodeCounter::Result OpcodeCounter::run(llvm::Function &Func,
llvm::FunctionAnalysisManager &) {
return generateOpcodeMap(Func);
}
PreservedAnalyses OpcodeCounterPrinter::run(Function &Func,
FunctionAnalysisManager &FAM) {
auto &OpcodeMap = FAM.getResult<OpcodeCounter>(Func);
// In the legacy PM, the following string is printed automatically by the
// pass manager. For the sake of consistency, we're adding this here so that
// it's also printed when using the new PM.
OS << "Printing analysis 'OpcodeCounter Pass' for function '"
<< Func.getName() << "':\n";
printOpcodeCounterResult(OS, OpcodeMap);
return PreservedAnalyses::all();
}
//-----------------------------------------------------------------------------
// New PM Registration
//-----------------------------------------------------------------------------
llvm::PassPluginLibraryInfo getOpcodeCounterPluginInfo() {
return {
LLVM_PLUGIN_API_VERSION, "OpcodeCounter", LLVM_VERSION_STRING,
[](PassBuilder &PB) {
// #1 REGISTRATION FOR "opt -passes=print<opcode-counter>"
// Register OpcodeCounterPrinter so that it can be used when
// specifying pass pipelines with `-passes=`.
PB.registerPipelineParsingCallback(
[&](StringRef Name, FunctionPassManager &FPM,
ArrayRef<PassBuilder::PipelineElement>) {
if (Name == "print<opcode-counter>") {
FPM.addPass(OpcodeCounterPrinter(llvm::errs()));
return true;
}
return false;
});
// #2 REGISTRATION FOR "-O{1|2|3|s}"
// Register OpcodeCounterPrinter as a step of an existing pipeline.
// The insertion point is specified by using the
// 'registerVectorizerStartEPCallback' callback. To be more precise,
// using this callback means that OpcodeCounterPrinter will be called
// whenever the vectoriser is used (i.e. when using '-O{1|2|3|s}'.
PB.registerVectorizerStartEPCallback(
[](llvm::FunctionPassManager &PM,
llvm::OptimizationLevel Level) {
PM.addPass(OpcodeCounterPrinter(llvm::errs()));
});
// #3 REGISTRATION FOR "FAM.getResult<OpcodeCounter>(Func)"
// Register OpcodeCounter as an analysis pass. This is required so that
// OpcodeCounterPrinter (or any other pass) can request the results
// of OpcodeCounter.
PB.registerAnalysisRegistrationCallback(
[](FunctionAnalysisManager &FAM) {
FAM.registerPass([&] { return OpcodeCounter(); });
});
}
};
}
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getOpcodeCounterPluginInfo();
}
//------------------------------------------------------------------------------
// Helper functions - implementation
//------------------------------------------------------------------------------
static void printOpcodeCounterResult(raw_ostream &OutS,
const ResultOpcodeCounter &OpcodeMap) {
OutS << "================================================="
<< "\n";
OutS << "LLVM-TUTOR: OpcodeCounter results\n";
OutS << "=================================================\n";
const char *str1 = "OPCODE";
const char *str2 = "#TIMES USED";
OutS << format("%-20s %-10s\n", str1, str2);
OutS << "-------------------------------------------------"
<< "\n";
for (auto &Inst : OpcodeMap) {
OutS << format("%-20s %-10lu\n", Inst.first().str().c_str(),
Inst.second);
}
OutS << "-------------------------------------------------"
<< "\n\n";
}