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