[lldb] Simplify DumpValueObjectOptions::PointerDepth (NFC) (#117504)
[llvm-project.git] / bolt / lib / Passes / StokeInfo.cpp
blobdd033508d200c10a04a7728e53daa95c9631ea18
1 //===- bolt/Passes/StokeInfo.cpp ------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the StokeInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "bolt/Passes/StokeInfo.h"
14 #include "bolt/Core/BinaryFunctionCallGraph.h"
15 #include "bolt/Passes/DataflowInfoManager.h"
16 #include "llvm/Support/CommandLine.h"
18 #define DEBUG_TYPE "stoke"
20 using namespace llvm;
21 using namespace bolt;
23 namespace opts {
24 cl::OptionCategory StokeOptCategory("STOKE pass options");
26 static cl::opt<std::string>
27 StokeOutputDataFilename("stoke-out",
28 cl::desc("output data (.csv) for Stoke's use"),
29 cl::Optional,
30 cl::cat(StokeOptCategory));
33 namespace llvm {
34 namespace bolt {
36 void getRegNameFromBitVec(const BinaryContext &BC, const BitVector &RegV,
37 std::set<std::string> *NameVec = nullptr) {
38 for (int RegIdx : RegV.set_bits()) {
39 LLVM_DEBUG(dbgs() << BC.MRI->getName(RegIdx) << " ");
40 if (NameVec)
41 NameVec->insert(std::string(BC.MRI->getName(RegIdx)));
43 LLVM_DEBUG(dbgs() << "\n");
46 void StokeInfo::checkInstr(const BinaryFunction &BF, StokeFuncInfo &FuncInfo) {
47 MCPlusBuilder *MIB = BF.getBinaryContext().MIB.get();
48 BitVector RegV(NumRegs, false);
49 for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {
50 if (BB->empty())
51 continue;
53 // Skip function with exception handling.
54 if (BB->throw_size() || BB->lp_size()) {
55 FuncInfo.Omitted = true;
56 return;
59 for (const MCInst &It : *BB) {
60 if (MIB->isPseudo(It))
61 continue;
62 // skip function with exception handling yet
63 if (MIB->isInvoke(It)) {
64 FuncInfo.Omitted = true;
65 return;
67 // check if this function contains call instruction
68 if (MIB->isCall(It)) {
69 FuncInfo.HasCall = true;
70 const MCSymbol *TargetSymbol = MIB->getTargetSymbol(It);
71 // if it is an indirect call, skip
72 if (TargetSymbol == nullptr) {
73 FuncInfo.Omitted = true;
74 return;
77 // check if this function modify stack or heap
78 // TODO: more accurate analysis
79 bool IsPush = MIB->isPush(It);
80 bool IsRipAddr = MIB->hasPCRelOperand(It);
81 if (IsPush)
82 FuncInfo.StackOut = true;
84 if (MIB->mayStore(It) && !IsPush && !IsRipAddr)
85 FuncInfo.HeapOut = true;
87 if (IsRipAddr)
88 FuncInfo.HasRipAddr = true;
89 } // end of for (auto &It : ...)
90 } // end of for (auto *BB : ...)
93 bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
94 RegAnalysis &RA, StokeFuncInfo &FuncInfo) {
96 std::string Name = BF.getSymbol()->getName().str();
98 if (!BF.isSimple() || BF.isMultiEntry() || BF.empty())
99 return false;
100 BF.getBinaryContext().outs()
101 << " STOKE-INFO: analyzing function " << Name << "\n";
103 FuncInfo.FuncName = Name;
104 FuncInfo.Offset = BF.getFileOffset();
105 FuncInfo.Size = BF.getMaxSize();
106 FuncInfo.NumInstrs = BF.getNumNonPseudos();
107 FuncInfo.NumBlocks = BF.size();
108 // early stop for large functions
109 if (FuncInfo.NumInstrs > 500)
110 return false;
112 FuncInfo.IsLoopFree = BF.isLoopFree();
113 if (!FuncInfo.IsLoopFree) {
114 const BinaryLoopInfo &BLI = BF.getLoopInfo();
115 FuncInfo.NumLoops = BLI.OuterLoops;
116 FuncInfo.MaxLoopDepth = BLI.MaximumDepth;
119 FuncInfo.HotSize = BF.estimateHotSize();
120 FuncInfo.TotalSize = BF.estimateSize();
121 FuncInfo.Score = BF.getFunctionScore();
123 checkInstr(BF, FuncInfo);
125 // register analysis
126 BinaryBasicBlock &EntryBB = BF.front();
127 assert(EntryBB.isEntryPoint() && "Weird, this should be the entry block!");
129 MCInst *FirstNonPseudo = EntryBB.getFirstNonPseudoInstr();
130 if (!FirstNonPseudo)
131 return false;
133 LLVM_DEBUG(dbgs() << "\t [DefIn]\n\t ");
134 BitVector LiveInBV =
135 *(DInfo.getLivenessAnalysis().getStateAt(FirstNonPseudo));
136 LiveInBV &= DefaultDefInMask;
137 getRegNameFromBitVec(BF.getBinaryContext(), LiveInBV, &FuncInfo.DefIn);
139 LLVM_DEBUG(dbgs() << "\t [LiveOut]\n\t ");
140 BitVector LiveOutBV = RA.getFunctionClobberList(&BF);
141 LiveOutBV &= DefaultLiveOutMask;
142 getRegNameFromBitVec(BF.getBinaryContext(), LiveOutBV, &FuncInfo.LiveOut);
144 BF.getBinaryContext().outs() << " STOKE-INFO: end function \n";
145 return true;
148 Error StokeInfo::runOnFunctions(BinaryContext &BC) {
149 BC.outs() << "STOKE-INFO: begin of stoke pass\n";
151 std::ofstream Outfile;
152 if (!opts::StokeOutputDataFilename.empty()) {
153 Outfile.open(opts::StokeOutputDataFilename);
154 } else {
155 BC.errs() << "STOKE-INFO: output file is required\n";
156 return Error::success();
159 // check some context meta data
160 LLVM_DEBUG(dbgs() << "\tTarget: " << BC.TheTarget->getName() << "\n");
161 LLVM_DEBUG(dbgs() << "\tTripleName " << BC.TripleName << "\n");
162 LLVM_DEBUG(dbgs() << "\tgetNumRegs " << BC.MRI->getNumRegs() << "\n");
164 BinaryFunctionCallGraph CG = buildCallGraph(BC);
165 RegAnalysis RA(BC, &BC.getBinaryFunctions(), &CG);
167 NumRegs = BC.MRI->getNumRegs();
168 assert(NumRegs > 0 && "STOKE-INFO: the target register number is incorrect!");
170 DefaultDefInMask.resize(NumRegs, false);
171 DefaultLiveOutMask.resize(NumRegs, false);
173 BC.MIB->getDefaultDefIn(DefaultDefInMask);
174 BC.MIB->getDefaultLiveOut(DefaultLiveOutMask);
176 getRegNameFromBitVec(BC, DefaultDefInMask);
177 getRegNameFromBitVec(BC, DefaultLiveOutMask);
179 StokeFuncInfo FuncInfo;
180 // analyze all functions
181 FuncInfo.printCsvHeader(Outfile);
182 for (auto &BF : BC.getBinaryFunctions()) {
183 DataflowInfoManager DInfo(BF.second, &RA, nullptr);
184 FuncInfo.reset();
185 if (checkFunction(BF.second, DInfo, RA, FuncInfo))
186 FuncInfo.printData(Outfile);
189 BC.outs() << "STOKE-INFO: end of stoke pass\n";
190 return Error::success();
193 } // namespace bolt
194 } // namespace llvm