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