[SLP] Add cost model for `llvm.powi.*` intrinsics (REAPPLIED)
[llvm-project.git] / bolt / lib / Passes / StokeInfo.cpp
blobdf6d85aced4e9d5d6f1e985da61f555e701bc178
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/Passes/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 (BinaryBasicBlock *BB : BF.layout()) {
50 if (BB->empty())
51 continue;
53 for (MCInst &It : *BB) {
54 if (MIB->isPseudo(It))
55 continue;
56 // skip function with exception handling yet
57 if (MIB->isEHLabel(It) || MIB->isInvoke(It)) {
58 FuncInfo.Omitted = true;
59 return;
61 // check if this function contains call instruction
62 if (MIB->isCall(It)) {
63 FuncInfo.HasCall = true;
64 const MCSymbol *TargetSymbol = MIB->getTargetSymbol(It);
65 // if it is an indirect call, skip
66 if (TargetSymbol == nullptr) {
67 FuncInfo.Omitted = true;
68 return;
71 // check if this function modify stack or heap
72 // TODO: more accurate analysis
73 bool IsPush = MIB->isPush(It);
74 bool IsRipAddr = MIB->hasPCRelOperand(It);
75 if (IsPush)
76 FuncInfo.StackOut = true;
78 if (MIB->isStore(It) && !IsPush && !IsRipAddr)
79 FuncInfo.HeapOut = true;
81 if (IsRipAddr)
82 FuncInfo.HasRipAddr = true;
83 } // end of for (auto &It : ...)
84 } // end of for (auto *BB : ...)
87 bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,
88 RegAnalysis &RA, StokeFuncInfo &FuncInfo) {
90 std::string Name = BF.getSymbol()->getName().str();
92 if (!BF.isSimple() || BF.isMultiEntry() || BF.empty())
93 return false;
94 outs() << " STOKE-INFO: analyzing function " << Name << "\n";
96 FuncInfo.FuncName = Name;
97 FuncInfo.Offset = BF.getFileOffset();
98 FuncInfo.Size = BF.getMaxSize();
99 FuncInfo.NumInstrs = BF.getNumNonPseudos();
100 FuncInfo.NumBlocks = BF.size();
101 // early stop for large functions
102 if (FuncInfo.NumInstrs > 500)
103 return false;
105 FuncInfo.IsLoopFree = BF.isLoopFree();
106 if (!FuncInfo.IsLoopFree) {
107 const BinaryLoopInfo &BLI = BF.getLoopInfo();
108 FuncInfo.NumLoops = BLI.OuterLoops;
109 FuncInfo.MaxLoopDepth = BLI.MaximumDepth;
112 FuncInfo.HotSize = BF.estimateHotSize();
113 FuncInfo.TotalSize = BF.estimateSize();
114 FuncInfo.Score = BF.getFunctionScore();
116 checkInstr(BF, FuncInfo);
118 // register analysis
119 BinaryBasicBlock &EntryBB = BF.front();
120 assert(EntryBB.isEntryPoint() && "Weird, this should be the entry block!");
122 MCInst *FirstNonPseudo = EntryBB.getFirstNonPseudoInstr();
123 if (!FirstNonPseudo)
124 return false;
126 LLVM_DEBUG(dbgs() << "\t [DefIn]\n\t ");
127 BitVector LiveInBV =
128 *(DInfo.getLivenessAnalysis().getStateAt(FirstNonPseudo));
129 LiveInBV &= DefaultDefInMask;
130 getRegNameFromBitVec(BF.getBinaryContext(), LiveInBV, &FuncInfo.DefIn);
132 LLVM_DEBUG(dbgs() << "\t [LiveOut]\n\t ");
133 BitVector LiveOutBV = RA.getFunctionClobberList(&BF);
134 LiveOutBV &= DefaultLiveOutMask;
135 getRegNameFromBitVec(BF.getBinaryContext(), LiveOutBV, &FuncInfo.LiveOut);
137 outs() << " STOKE-INFO: end function \n";
138 return true;
141 void StokeInfo::runOnFunctions(BinaryContext &BC) {
142 outs() << "STOKE-INFO: begin of stoke pass\n";
144 std::ofstream Outfile;
145 if (!opts::StokeOutputDataFilename.empty()) {
146 Outfile.open(opts::StokeOutputDataFilename);
147 } else {
148 errs() << "STOKE-INFO: output file is required\n";
149 return;
152 // check some context meta data
153 LLVM_DEBUG(dbgs() << "\tTarget: " << BC.TheTarget->getName() << "\n");
154 LLVM_DEBUG(dbgs() << "\tTripleName " << BC.TripleName << "\n");
155 LLVM_DEBUG(dbgs() << "\tgetNumRegs " << BC.MRI->getNumRegs() << "\n");
157 BinaryFunctionCallGraph CG = buildCallGraph(BC);
158 RegAnalysis RA(BC, &BC.getBinaryFunctions(), &CG);
160 NumRegs = BC.MRI->getNumRegs();
161 assert(NumRegs > 0 && "STOKE-INFO: the target register number is incorrect!");
163 DefaultDefInMask.resize(NumRegs, false);
164 DefaultLiveOutMask.resize(NumRegs, false);
166 BC.MIB->getDefaultDefIn(DefaultDefInMask);
167 BC.MIB->getDefaultLiveOut(DefaultLiveOutMask);
169 getRegNameFromBitVec(BC, DefaultDefInMask);
170 getRegNameFromBitVec(BC, DefaultLiveOutMask);
172 StokeFuncInfo FuncInfo;
173 // analyze all functions
174 FuncInfo.printCsvHeader(Outfile);
175 for (auto &BF : BC.getBinaryFunctions()) {
176 DataflowInfoManager DInfo(BF.second, &RA, nullptr);
177 FuncInfo.reset();
178 if (checkFunction(BF.second, DInfo, RA, FuncInfo))
179 FuncInfo.printData(Outfile);
182 outs() << "STOKE-INFO: end of stoke pass\n";
185 } // namespace bolt
186 } // namespace llvm