1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "instrument.h"
17 #include "cgbb.h"
18 #include "mir_builder.h"
19 #include "mpl_logging.h"
20
21 namespace maple {
GetProfCntSymbolName(const std::string & funcName)22 std::string GetProfCntSymbolName(const std::string &funcName)
23 {
24 return funcName + "_counter";
25 }
26
RegisterInFuncInfo(MIRFunction & func,const MIRSymbol & counter,uint64 elemCnt,uint32 cfgHash)27 static inline void RegisterInFuncInfo(MIRFunction &func, const MIRSymbol &counter, uint64 elemCnt, uint32 cfgHash)
28 {
29 if (elemCnt == 0) {
30 return;
31 }
32 auto funcStrIdx = GlobalTables::GetStrTable().GetStrIdxFromName(namemangler::kprefixProfFuncDesc + func.GetName());
33 MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(funcStrIdx);
34 CHECK_FATAL(sym, "function have not generated, please check in CreateFuncInfo");
35 auto *funcInfoMirConst = static_cast<MIRAggConst *>(sym->GetKonst());
36 MIRType *u32Ty = GlobalTables::GetTypeTable().GetUInt32();
37 MIRIntConst *cfgHashConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(cfgHash, *u32Ty);
38 MIRIntConst *eleCntMirConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(elemCnt, *u32Ty);
39 auto *counterConst = func.GetModule()->GetMemPool()->New<MIRAddrofConst>(counter.GetStIdx(), 0,
40 *GlobalTables::GetTypeTable().GetPtr());
41 int num1 = 1;
42 int num2 = 2;
43 int num3 = 3;
44 int num4 = 4;
45 funcInfoMirConst->SetItem(num1, cfgHashConst, num2);
46 funcInfoMirConst->SetItem(num2, eleCntMirConst, num3);
47 funcInfoMirConst->SetItem(num3, counterConst, num4);
48 }
49
GetOrCreateFuncCounter(MIRFunction & func,uint32 elemCnt,uint32 cfgHash)50 MIRSymbol *GetOrCreateFuncCounter(MIRFunction &func, uint32 elemCnt, uint32 cfgHash)
51 {
52 auto *mirModule = func.GetModule();
53 std::string name = GetProfCntSymbolName(func.GetName());
54 auto nameStrIdx = GlobalTables::GetStrTable().GetStrIdxFromName(name);
55 MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(nameStrIdx);
56 if (sym != nullptr) {
57 return sym;
58 }
59 auto *elemType = GlobalTables::GetTypeTable().GetUInt64();
60 MIRArrayType &arrayType = *GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, elemCnt);
61 sym = mirModule->GetMIRBuilder()->CreateGlobalDecl(name.c_str(), arrayType, kScFstatic);
62 auto *profTab = mirModule->GetMemPool()->New<MIRAggConst>(*mirModule, arrayType);
63 MIRIntConst *indexConst = GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, *elemType);
64 for (uint32 i = 0; i < elemCnt; ++i) {
65 profTab->AddItem(indexConst, i);
66 }
67 sym->SetKonst(profTab);
68 sym->SetStorageClass(kScFstatic);
69 sym->sectionAttr = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName("mpl_counter");
70 RegisterInFuncInfo(func, *sym, elemCnt, cfgHash);
71 return sym;
72 }
73
74 template <class IRBB, class Edge>
GetInstrumentBBs(std::vector<IRBB * > & bbs,IRBB * commonEntry) const75 void PGOInstrumentTemplate<IRBB, Edge>::GetInstrumentBBs(std::vector<IRBB *> &bbs, IRBB *commonEntry) const
76 {
77 std::vector<Edge *> iEdges;
78 mst.GetInstrumentEdges(iEdges);
79 std::unordered_set<IRBB *> visitedBBs;
80 for (auto &edge : iEdges) {
81 IRBB *src = edge->GetSrcBB();
82 IRBB *dest = edge->GetDestBB();
83 if (src->GetSuccs().size() <= 1) {
84 if (src == commonEntry) {
85 bbs.push_back(dest);
86 } else {
87 bbs.push_back(src);
88 }
89 } else if (!edge->IsCritical()) {
90 bbs.push_back(dest);
91 } else {
92 if (src->GetKind() == IRBB::kBBIgoto) {
93 if (visitedBBs.find(dest) == visitedBBs.end()) {
94 // In this case, we have to instrument it anyway
95 bbs.push_back(dest);
96 (void)visitedBBs.insert(dest);
97 }
98 } else {
99 CHECK_FATAL(false, "Unexpected case %d -> %d", src->GetId(), dest->GetId());
100 }
101 }
102 }
103 }
104
105 template <typename BB>
GetOnlyUnknownOutEdges()106 BBUseEdge<BB> *BBUseInfo<BB>::GetOnlyUnknownOutEdges()
107 {
108 BBUseEdge<BB> *ouEdge = nullptr;
109 for (auto *e : outEdges) {
110 if (!e->GetStatus()) {
111 CHECK_FATAL(!ouEdge, "have multiple unknown out edges");
112 ouEdge = e;
113 }
114 }
115 return ouEdge;
116 }
117
118 template <typename BB>
GetOnlyUnknownInEdges()119 BBUseEdge<BB> *BBUseInfo<BB>::GetOnlyUnknownInEdges()
120 {
121 BBUseEdge<BB> *ouEdge = nullptr;
122 for (auto *e : inEdges) {
123 if (!e->GetStatus()) {
124 CHECK_FATAL(!ouEdge, "have multiple unknown in edges");
125 ouEdge = e;
126 }
127 }
128 return ouEdge;
129 }
130
131 template <typename BB>
Dump()132 void BBUseInfo<BB>::Dump()
133 {
134 for (const auto &inE : inEdges) {
135 if (inE->GetStatus()) {
136 LogInfo::MapleLogger() << inE->GetSrcBB()->GetId() << "->" << inE->GetDestBB()->GetId()
137 << " c : " << inE->GetCount() << "\n";
138 }
139 }
140 for (const auto &outE : outEdges) {
141 if (outE->GetStatus()) {
142 LogInfo::MapleLogger() << outE->GetSrcBB()->GetId() << "->" << outE->GetDestBB()->GetId()
143 << " c : " << outE->GetCount() << "\n";
144 }
145 }
146 }
147
148 template class PGOInstrumentTemplate<maplebe::BB, maple::BBEdge<maplebe::BB>>;
149 template class PGOInstrumentTemplate<maplebe::BB, maple::BBUseEdge<maplebe::BB>>;
150 template class BBUseInfo<maplebe::BB>;
151 } /* namespace maple */
152