• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "optimize_common.h"
17 #include "cgbb.h"
18 #include "cg.h"
19 #include "cg_option.h"
20 #include "loop.h"
21 #include "securec.h"
22 
23 /* This file provides common class and function for cfgo and ico. */
24 namespace maplebe {
Run(const std::string & funcName,bool checkOnly)25 void Optimizer::Run(const std::string &funcName, bool checkOnly)
26 {
27     /* Initialize cfg optimization patterns */
28     InitOptimizePatterns();
29 
30     /* For each pattern, search cgFunc for optimization */
31     for (OptimizationPattern *p : diffPassPatterns) {
32         p->Search2Op(checkOnly);
33     }
34     /* Search the cgFunc for multiple possible optimizations in one pass */
35     if (!singlePassPatterns.empty()) {
36         BB *curBB = cgFunc->GetFirstBB();
37         bool flag = false;
38         while (curBB != nullptr) {
39             for (OptimizationPattern *p : singlePassPatterns) {
40                 if (p->Optimize(*curBB)) {
41                     flag = p->IsKeepPosition();
42                     p->SetKeepPosition(false);
43                     break;
44                 }
45             }
46 
47             if (flag) {
48                 flag = false;
49             } else {
50                 curBB = curBB->GetNext();
51             }
52         }
53     }
54 
55     if (CGOptions::IsDumpOptimizeCommonLog()) {
56         constexpr int arrSize = 80;
57         char post[arrSize];
58         errno_t cpyRet = strcpy_s(post, arrSize, "post-");
59         CHECK_FATAL(cpyRet == EOK, "call strcpy_s failed");
60         errno_t catRes = strcat_s(post, arrSize, name);
61         CHECK_FATAL(catRes == EOK, "call strcat_s failed ");
62         OptimizeLogger::GetLogger().Print(funcName);
63     }
64     OptimizeLogger::GetLogger().ClearLocal();
65 }
66 
Search2Op(bool noOptimize)67 void OptimizationPattern::Search2Op(bool noOptimize)
68 {
69     checkOnly = noOptimize;
70     BB *curBB = cgFunc->GetFirstBB();
71     while (curBB != nullptr) {
72         bool changed = false;
73         do {
74             changed = Optimize(*curBB);
75         } while (changed);
76         if (keepPosition) {
77             keepPosition = false;
78         } else {
79             curBB = curBB->GetNext();
80         }
81     }
82 }
83 
Log(uint32 bbID)84 void OptimizationPattern::Log(uint32 bbID)
85 {
86     OptimizeLogger::GetLogger().Log(patternName.c_str());
87     DotGenerator::SetColor(bbID, dotColor.c_str());
88 }
89 
90 std::map<uint32, std::string> DotGenerator::coloringMap;
91 
SetColor(uint32 bbID,const std::string & color)92 void DotGenerator::SetColor(uint32 bbID, const std::string &color)
93 {
94     coloringMap[bbID] = color;
95 }
96 
GetFileName(const MIRModule & mirModule,const std::string & filePreFix)97 std::string DotGenerator::GetFileName(const MIRModule &mirModule, const std::string &filePreFix)
98 {
99     std::string fileName;
100     if (!filePreFix.empty()) {
101         fileName.append(filePreFix);
102         fileName.append("-");
103     }
104     fileName.append(mirModule.GetFileName());
105     for (uint32 i = 0; i < fileName.length(); i++) {
106         if (fileName[i] == ';' || fileName[i] == '/' || fileName[i] == '|') {
107             fileName[i] = '_';
108         }
109     }
110 
111     fileName.append(".dot");
112     return fileName;
113 }
114 
IsBackEdgeForLoop(const CGFuncLoops & loop,const BB & from,const BB & to)115 static bool IsBackEdgeForLoop(const CGFuncLoops &loop, const BB &from, const BB &to)
116 {
117     const BB *header = loop.GetHeader();
118     if (header->GetId() == to.GetId()) {
119         for (auto *be : loop.GetBackedge()) {
120             if (be->GetId() == from.GetId()) {
121                 return true;
122             }
123         }
124     }
125     for (auto *inner : loop.GetInnerLoops()) {
126         if (IsBackEdgeForLoop(*inner, from, to)) {
127             return true;
128         }
129     }
130     return false;
131 }
IsBackEdge(const CGFunc & cgFunction,const BB & from,const BB & to)132 bool DotGenerator::IsBackEdge(const CGFunc &cgFunction, const BB &from, const BB &to)
133 {
134     for (const auto *loop : cgFunction.GetLoops()) {
135         if (IsBackEdgeForLoop(*loop, from, to)) {
136             return true;
137         }
138     }
139     return false;
140 }
141 
DumpEdge(const CGFunc & cgFunction,std::ofstream & cfgFileOfStream,bool isIncludeEH)142 void DotGenerator::DumpEdge(const CGFunc &cgFunction, std::ofstream &cfgFileOfStream, bool isIncludeEH)
143 {
144     FOR_ALL_BB_CONST(bb, &cgFunction) {
145         for (auto *succBB : bb->GetSuccs()) {
146             cfgFileOfStream << "BB" << bb->GetId();
147             cfgFileOfStream << " -> "
148                             << "BB" << succBB->GetId();
149             if (IsBackEdge(cgFunction, *bb, *succBB)) {
150                 cfgFileOfStream << " [color=red]";
151             } else {
152                 cfgFileOfStream << " [color=green]";
153             }
154             cfgFileOfStream << ";\n";
155         }
156         if (isIncludeEH) {
157             for (auto *ehSuccBB : bb->GetEhSuccs()) {
158                 cfgFileOfStream << "BB" << bb->GetId();
159                 cfgFileOfStream << " -> "
160                                 << "BB" << ehSuccBB->GetId();
161                 cfgFileOfStream << "[color=red]";
162                 cfgFileOfStream << ";\n";
163             }
164         }
165     }
166 }
167 
FoundListOpndRegNum(ListOperand & listOpnd,const Insn & insnObj,regno_t vReg)168 bool DotGenerator::FoundListOpndRegNum(ListOperand &listOpnd, const Insn &insnObj, regno_t vReg)
169 {
170     bool exist = false;
171     for (auto op : listOpnd.GetOperands()) {
172         RegOperand *regOpnd = static_cast<RegOperand *>(op);
173         if (op->IsRegister() && regOpnd->GetRegisterNumber() == vReg) {
174             LogInfo::MapleLogger() << "BB" << insnObj.GetBB()->GetId() << " [style=filled, fillcolor=red];\n";
175             exist = true;
176             break;
177         }
178     }
179     return exist;
180 }
181 
FoundMemAccessOpndRegNum(const MemOperand & memOperand,const Insn & insnObj,regno_t vReg)182 bool DotGenerator::FoundMemAccessOpndRegNum(const MemOperand &memOperand, const Insn &insnObj, regno_t vReg)
183 {
184     Operand *base = memOperand.GetBaseRegister();
185     Operand *offset = memOperand.GetIndexRegister();
186     bool exist = false;
187     if (base != nullptr && base->IsRegister()) {
188         RegOperand *regOpnd = static_cast<RegOperand *>(base);
189         if (regOpnd->GetRegisterNumber() == vReg) {
190             LogInfo::MapleLogger() << "BB" << insnObj.GetBB()->GetId() << " [style=filled, fillcolor=red];\n";
191             exist = true;
192         }
193     } else if (offset != nullptr && offset->IsRegister()) {
194         RegOperand *regOpnd = static_cast<RegOperand *>(offset);
195         if (regOpnd->GetRegisterNumber() == vReg) {
196             LogInfo::MapleLogger() << "BB" << insnObj.GetBB()->GetId() << " [style=filled, fillcolor=red];\n";
197             exist = true;
198         }
199     }
200     return exist;
201 }
202 
FoundNormalOpndRegNum(const RegOperand & regOpnd,const Insn & insnObj,regno_t vReg)203 bool DotGenerator::FoundNormalOpndRegNum(const RegOperand &regOpnd, const Insn &insnObj, regno_t vReg)
204 {
205     bool exist = false;
206     if (regOpnd.GetRegisterNumber() == vReg) {
207         LogInfo::MapleLogger() << "BB" << insnObj.GetBB()->GetId() << " [style=filled, fillcolor=red];\n";
208         exist = true;
209     }
210     return exist;
211 }
212 
DumpBBInstructions(const CGFunc & cgFunction,regno_t vReg,std::ofstream & cfgFile)213 void DotGenerator::DumpBBInstructions(const CGFunc &cgFunction, regno_t vReg, std::ofstream &cfgFile)
214 {
215     FOR_ALL_BB_CONST(bb, &cgFunction) {
216         if (vReg != 0) {
217             FOR_BB_INSNS_CONST(insn, bb) {
218                 bool found = false;
219                 uint32 opndNum = insn->GetOperandSize();
220                 for (uint32 i = 0; i < opndNum; ++i) {
221                     Operand &opnd = insn->GetOperand(i);
222                     if (opnd.IsList()) {
223                         auto &listOpnd = static_cast<ListOperand &>(opnd);
224                         found = FoundListOpndRegNum(listOpnd, *insn, vReg);
225                     } else if (opnd.IsMemoryAccessOperand()) {
226                         auto &memOpnd = static_cast<MemOperand &>(opnd);
227                         found = FoundMemAccessOpndRegNum(memOpnd, *insn, vReg);
228                     } else {
229                         if (opnd.IsRegister()) {
230                             auto &regOpnd = static_cast<RegOperand &>(opnd);
231                             found = FoundNormalOpndRegNum(regOpnd, *insn, vReg);
232                         }
233                     }
234                     if (found) {
235                         break;
236                     }
237                 }
238                 if (found) {
239                     break;
240                 }
241             }
242         }
243         cfgFile << "BB" << bb->GetId() << "[";
244         auto it = coloringMap.find(bb->GetId());
245         if (it != coloringMap.end()) {
246             cfgFile << "style=filled,fillcolor=" << it->second << ",";
247         }
248         if (bb->GetKind() == BB::kBBIf) {
249             cfgFile << "shape=diamond,label= \" BB" << bb->GetId() << ":\n";
250         } else {
251             cfgFile << "shape=box,label= \" BB" << bb->GetId() << ":\n";
252         }
253         cfgFile << "{ ";
254         cfgFile << bb->GetKindName() << "\n";
255         cfgFile << bb->GetFrequency() << "\n";
256         if (bb->GetLabIdx() != 0) {
257             cfgFile << "LabIdx=" << bb->GetLabIdx() << "\n";
258         }
259         cfgFile << "}\"];\n";
260     }
261 }
262 
263 /* Generate dot file for cfg */
GenerateDot(const std::string & preFix,const CGFunc & cgFunc,const MIRModule & mod,bool includeEH,const std::string fname,regno_t vReg)264 void DotGenerator::GenerateDot(const std::string &preFix, const CGFunc &cgFunc, const MIRModule &mod, bool includeEH,
265                                const std::string fname, regno_t vReg)
266 {
267     std::ofstream cfgFile;
268     std::streambuf *coutBuf = std::cout.rdbuf(); /* keep original cout buffer */
269     std::streambuf *buf = cfgFile.rdbuf();
270     std::cout.rdbuf(buf);
271     std::string fileName = GetFileName(mod, (preFix + "-" + fname));
272 
273     cfgFile.open(fileName, std::ios::trunc);
274     CHECK_FATAL(cfgFile.is_open(), "Failed to open output file: %s", fileName.c_str());
275     cfgFile << "digraph {\n";
276     /* dump edge */
277     DumpEdge(cgFunc, cfgFile, includeEH);
278 
279     /* dump instruction in each BB */
280     DumpBBInstructions(cgFunc, vReg, cfgFile);
281 
282     cfgFile << "}\n";
283     coloringMap.clear();
284     cfgFile.flush();
285     cfgFile.close();
286     std::cout.rdbuf(coutBuf);
287 }
288 
Print(const std::string & funcName)289 void OptimizeLogger::Print(const std::string &funcName)
290 {
291     if (!localStat.empty()) {
292         LogInfo::MapleLogger() << funcName << '\n';
293         for (const auto &localStatPair : localStat) {
294             LogInfo::MapleLogger() << "Optimized " << localStatPair.first << ":" << localStatPair.second << "\n";
295         }
296 
297         ClearLocal();
298         LogInfo::MapleLogger() << "Total:" << '\n';
299         for (const auto &globalStatPair : globalStat) {
300             LogInfo::MapleLogger() << "Optimized " << globalStatPair.first << ":" << globalStatPair.second << "\n";
301         }
302     }
303 }
304 
Log(const std::string & patternName)305 void OptimizeLogger::Log(const std::string &patternName)
306 {
307     auto itemInGlobal = globalStat.find(patternName);
308     if (itemInGlobal != globalStat.end()) {
309         itemInGlobal->second++;
310     } else {
311         (void)globalStat.emplace(std::pair<const std::string, int>(patternName, 1));
312     }
313     auto itemInLocal = localStat.find(patternName);
314     if (itemInLocal != localStat.end()) {
315         itemInLocal->second++;
316     } else {
317         (void)localStat.emplace(std::pair<const std::string, int>(patternName, 1));
318     }
319 }
320 
ClearLocal()321 void OptimizeLogger::ClearLocal()
322 {
323     localStat.clear();
324 }
325 } /* namespace maplebe */
326