• 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 "phase_impl.h"
17 #include <cstdlib>
18 #include "mpl_timer.h"
19 
20 namespace maple {
21 // ========== FuncOptimizeImpl ==========
FuncOptimizeImpl(MIRModule & mod,KlassHierarchy * kh,bool currTrace)22 FuncOptimizeImpl::FuncOptimizeImpl(MIRModule &mod, KlassHierarchy *kh, bool currTrace)
23     : klassHierarchy(kh), trace(currTrace), module(&mod)
24 {
25     builder = new (std::nothrow) MIRBuilderExt(module);
26     CHECK_FATAL(builder != nullptr, "New fail in FuncOptimizeImpl ctor!");
27 }
28 
~FuncOptimizeImpl()29 FuncOptimizeImpl::~FuncOptimizeImpl()
30 {
31     if (builder != nullptr) {
32         delete builder;
33         builder = nullptr;
34     }
35     klassHierarchy = nullptr;
36     currFunc = nullptr;
37     module = nullptr;
38 }
39 
CreateLocalBuilder(pthread_mutex_t & mtx)40 void FuncOptimizeImpl::CreateLocalBuilder(pthread_mutex_t &mtx)
41 {
42     // Each thread needs to use its own MIRBuilderExt.
43     builder = new (std::nothrow) MIRBuilderExt(module, &mtx);
44     CHECK_FATAL(builder != nullptr, "New fail in CreateLocalBuilder ctor!");
45 }
46 
ProcessFunc(MIRFunction * func)47 void FuncOptimizeImpl::ProcessFunc(MIRFunction *func)
48 {
49     currFunc = func;
50     SetCurrentFunction(*func);
51     if (func->GetBody() != nullptr) {
52         ProcessBlock(*func->GetBody());
53     }
54 }
55 
ProcessBlock(StmtNode & stmt)56 void FuncOptimizeImpl::ProcessBlock(StmtNode &stmt)
57 {
58     switch (stmt.GetOpCode()) {
59         case OP_if: {
60             ProcessStmt(stmt);
61             IfStmtNode &ifStmtNode = static_cast<IfStmtNode &>(stmt);
62             if (ifStmtNode.GetThenPart() != nullptr) {
63                 ProcessBlock(*ifStmtNode.GetThenPart());
64             }
65             if (ifStmtNode.GetElsePart() != nullptr) {
66                 ProcessBlock(*ifStmtNode.GetElsePart());
67             }
68             break;
69         }
70         case OP_while:
71         case OP_dowhile: {
72             ProcessStmt(stmt);
73             WhileStmtNode &whileStmtNode = static_cast<WhileStmtNode &>(stmt);
74             if (whileStmtNode.GetBody() != nullptr) {
75                 ProcessBlock(*whileStmtNode.GetBody());
76             }
77             break;
78         }
79         case OP_block: {
80             BlockNode &block = static_cast<BlockNode &>(stmt);
81             for (StmtNode *stmtNode = block.GetFirst(), *next = nullptr; stmtNode != nullptr; stmtNode = next) {
82                 SetCurrentBlock(block);
83                 ProcessBlock(*stmtNode);
84                 next = stmtNode->GetNext();
85             }
86             break;
87         }
88         default: {
89             ProcessStmt(stmt);
90             break;
91         }
92     }
93 }
94 
95 // ========== FuncOptimizeIterator ==========
96 thread_local FuncOptimizeImpl *FuncOptimizeIterator::phaseImplLocal = nullptr;
97 
FuncOptimizeIterator(const std::string & phaseName,std::unique_ptr<FuncOptimizeImpl> phaseImpl)98 FuncOptimizeIterator::FuncOptimizeIterator(const std::string &phaseName, std::unique_ptr<FuncOptimizeImpl> phaseImpl)
99     : MplScheduler(phaseName), phaseImpl(std::move(phaseImpl))
100 {
101     char *envStr = getenv("MP_DUMPTIME");
102     mplDumpTime = (envStr != nullptr && atoi(envStr) == 1);
103 }
104 
105 FuncOptimizeIterator::~FuncOptimizeIterator() = default;
106 
Run(uint32 threadNum,bool isSeq)107 void FuncOptimizeIterator::Run(uint32 threadNum, bool isSeq)
108 {
109     if (threadNum == 1) {
110         RunSerial();
111     } else {
112         RunParallel(threadNum, isSeq);
113     }
114 }
115 
116 constexpr double kMicroseconds2Milli = 1000.0;
RunSerial()117 void FuncOptimizeIterator::RunSerial()
118 {
119     MPLTimer timer;
120     if (mplDumpTime) {
121         timer.Start();
122     }
123 
124     CHECK_NULL_FATAL(phaseImpl);
125     for (MIRFunction *func : phaseImpl->GetMIRModule().GetFunctionList()) {
126         auto dumpPhase = [this, func](bool dumpOption, std::string &&s) {
127             if (dumpOption) {
128                 LogInfo::MapleLogger() << ">>>>> Dump " << s << schedulerName << " <<<<<\n";
129                 func->Dump();
130                 LogInfo::MapleLogger() << ">>>>> Dump " << s << schedulerName << " end <<<<<\n";
131             }
132         };
133         bool dumpFunc = (Options::dumpFunc == "*" || Options::dumpFunc == func->GetName()) &&
134                         (Options::dumpPhase == "*" || Options::dumpPhase == schedulerName);
135         dumpPhase(Options::dumpBefore && dumpFunc, "before ");
136         phaseImpl->SetDump(dumpFunc);
137         phaseImpl->ProcessFunc(func);
138         dumpPhase(Options::dumpAfter && dumpFunc, "after ");
139     }
140 
141     phaseImpl->Finish();
142 
143     if (mplDumpTime) {
144         timer.Stop();
145         INFO(kLncInfo, "FuncOptimizeIterator::RunSerial (%s): %lf ms", schedulerName.c_str(),
146              timer.ElapsedMicroseconds() / kMicroseconds2Milli);
147     }
148 }
149 
RunParallel(uint32 threadNum,bool isSeq)150 void FuncOptimizeIterator::RunParallel(uint32 threadNum, bool isSeq)
151 {
152     MPLTimer timer;
153     if (mplDumpTime) {
154         timer.Start();
155     }
156     Reset();
157 
158     CHECK_NULL_FATAL(phaseImpl);
159     for (MIRFunction *func : phaseImpl->GetMIRModule().GetFunctionList()) {
160         std::unique_ptr<Task> task = std::make_unique<Task>(*func);
161         ASSERT_NOT_NULL(task);
162         AddTask(*task.get());
163         tasksUniquePtr.emplace_back(std::move(task));
164     }
165 
166     if (mplDumpTime) {
167         timer.Stop();
168         INFO(kLncInfo, "FuncOptimizeIterator::RunParallel (%s): AddTask() = %lf ms", schedulerName.c_str(),
169              timer.ElapsedMicroseconds() / kMicroseconds2Milli);
170 
171         timer.Start();
172     }
173 
174     int ret = RunTask(threadNum, isSeq);
175     CHECK_FATAL(ret == 0, "RunTask failed");
176     phaseImpl->Finish();
177     Reset();
178 
179     if (mplDumpTime) {
180         timer.Stop();
181         INFO(kLncInfo, "FuncOptimizeIterator::RunParallel (%s): RunTask() = %lf ms", schedulerName.c_str(),
182              timer.ElapsedMicroseconds() / kMicroseconds2Milli);
183     }
184 }
185 }  // namespace maple
186