同步操作将从 方舟编译器/OpenArkCompiler 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
OpenArkCompiler comes with a series of optimization measures managed in phase mode. This document describes how to design, use, and define a phase by taking middle end as an example.
Middle end involves ModulePhase and MeFuncPhase inherited from the Phase class. The Run method is the most important for the Phase class. Two overloads of the method depend on whether analysis is required.
virtual AnalysisResult *Run(MeFunction *ir, MeFuncResultMgr *frm) {
return nullptr;
}
// By default mrm will not be used because most ME phases do not need
// IPA result. For those will use IPA result, this function will be overrode.
virtual AnalysisResult *Run(MeFunction *ir, MeFuncResultMgr *frm, ModuleResultMgr *mrm) {
return Run(ir, frm);
}
Therefore, when adding a new phase, at least one Run method must be implemented, and the PhaseName method must be overridden to return the phase name. The following uses rclowering as an example:
class MeDoRCLowering : public MeFuncPhase {
public:
MeDoRCLowering(MePhaseID id) : MeFuncPhase(id) {}
virtual ~MeDoRCLowering() = default;
AnalysisResult *Run(MeFunction*, MeFuncResultMgr*, ModuleResultMgr*) override;
const std::string PhaseName() const override {
return "rclowering";
}
};
AnalysisResult *MeDoRCLowering::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) {
KlassHierarchy *kh = static_cast<KlassHierarchy*>(mrm->GetAnalysisResult(MoPhase_CHA, &func->GetMIRModule()));
DASSERT(kh != nullptr, "KlassHierarchy has problem");
MeIRMap *hmap = static_cast<MeIRMap*>(m->GetAnalysisResult(MeFuncPhase_IRMAP, func));
DASSERT(hmap != nullptr, "hssamap has problem");
RCLowering rclowering(func, kh);
MIRFunction *mirfunction = func->GetMirFunc();
DASSERT(mirfunction->GetModule()->CurFunction() == mirfunction, "unexpected CurFunction");
string funcname = mirfunction->GetName();
if (DEBUGFUNC(func)) {
LogInfo::MapleLogger() << "Handling function " << funcname << std::endl;
}
...
PhaseManager creates, manages, and runs phases. PhaseManager is classified into ModulePhaseManager and MeFuncPhaseManager. PhaseManager registers all phases it supports so that users can add phases through the add phase interface.
1. Registering a phase
Take MeFuncPhaseManager as an example. It is registered through the RegisterFuncPhases method. The registered phase is managed through the registeredPhases map.
void MeFuncPhaseManager::RegisterFuncPhases() {
// register all Funcphases defined in mephases.def
#define FUNCTPHASE(id, mephase) \
do { \
void *buf = GetMemAllocator()->GetMemPool()->Malloc(sizeof(mephase(id))); \
ASSERT(buf != nullptr, "null ptr check"); \
RegisterPhase(id, (new (buf) mephase(id))); \
} while (0);
#define FUNCAPHASE(id, mephase)
do { \
void *buf = GetMemAllocator()->GetMemPool()->Malloc(sizeof(mephase(id))); \
ASSERT(buf != nullptr, "null ptr check"); \
RegisterPhase(id, (new (buf) mephase(id))); \
arFuncManager.AddAnalysisPhase(id,(static_cast<MeFuncPhase*>(GetPhase(id))));\
} while (0);
#include "mephases.def"
#undef FUNCTPHASE
#undef FUNCAPHASE
}
void RegisterPhase(PhaseId id, Phase *p) {
registeredPhases[id] = p;
}
Here, a macro is used for registration, which facilitates the management of phases to be registered. Only the corresponding .def file needs editing. The content of the mephases.def file is as follows. The first parameter is id, and the second parameter is the phase class name.
FUNCAPHASE(MeFuncPhase_SSATAB, MeDoSSATab)
FUNCAPHASE(MeFuncPhase_ALIASCLASS, MeDoAliasClass)
FUNCAPHASE(MeFuncPhase_SSA, MeDoSSA)
To support the rclowering phase mentioned above, add the following line:
FUNCTPHASE(MeFuncPhase_RCLOWERING, MeDoRCLowering)
2. Adding a phase
The phase manager subclass provides interfaces for adding phases. After processing input, the interfaces call the AddPhase method of the PhaseManager base class.
void MeFuncPhaseManager::AddPhasesNoDefault(std::vector<std::string> &phases) {
for (unsigned i = 0; i < phases.size(); i++) {
PhaseManager::AddPhase(phases[i].c_str());
}
DASSERT(phases.size() == GetphaseSeq()->size(), "invalid phase name");
}
void AddPhase(const std::string &pname) {
for (auto it = RegPhaseBegin(); it != RegPhaseEnd(); it++) {
if (GetPhaseName(it) == pname) {
phaseSequences.push_back(GetPhaseId(it));
phaseTimers.push_back(0);
return;
}
}
...
The added phase is managed by MapleVector.
In addition, users can use the framework composed of InterleavedManager and DriverRunner to manage phases more effectively.
1. InterleavedManager
InterleavedManager creates, manages, and runs phase managers. By invoking the AddPhases interface, InterleavedManager creates a phase manager of the corresponding type and adds it to MapleVector. At the same time, the registration and adding of phases corresponding to the phase managers are triggered automatically.
void InterleavedManager::AddPhases(vector<string> &phases, bool isModulePhase, bool timephases, bool genmpl) {
ModuleResultMgr *mrm = nullptr;
if (!phaseManagers.empty()) {
// ModuleResult such class hierarchy need to be carried on
ModulePhaseManager *mpm = dynamic_cast<ModulePhaseManager*>(phaseManagers[phaseManagers.size()-1]);
MeFuncPhaseManager *mepm = dynamic_cast<MeFuncPhaseManager*>(phaseManagers[phaseManagers.size()-1]);
if (mpm != nullptr) {
mrm = mpm->GetModResultMgr();
} else if (mepm != nullptr) {
mrm = mepm->GetModResultMgr();
}
}
if (isModulePhase) {
ModulePhaseManager *mpm = GetMempool()->New<ModulePhaseManager>(GetMempool(), &mirmodule, mrm);
mpm->RegisterModulePhases();
mpm->AddModulePhases(phases);
if (timephases) {
mpm->SetTimePhases(true);
}
phaseManagers.push_back(mpm);
...
The Run method of InterleavedManager runs all managed phase managers in turn.
void InterleavedManager::Run() {
for (PhaseManager *const &pm : phaseManagers) {
if (dynamic_cast<MeFuncPhaseManager*>(pm)) {
MeFuncPhaseManager *fpm = static_cast<MeFuncPhaseManager*>(pm);
unsigned long rangeNum = 0;
MapleVector<MIRFunction*> *compList;
if (!mirmodule.GetCompilationList().empty()) {
...
2. DriverRunner
DriverRunner contains all the processes from an .mpl file to an optimized final file. The ParseInput method is used to parse the .mpl file. The ProcessMpl2mplAndMePhases method is used to manage and run phases through InterleavedManager.
DriverRunner also manages phases through a macro. All phases in the phases.def file are traversed and corresponding phase managers are created through the InitPhases interface.
The content of the phases.def file is as follows:
// Phase arguments are: name, condition. By default, all phases are required, so
// the condition value is 'true'.
// You can use condition to control these phases and your custom phases. E.g.
// ADD_PHASE("custom_phase", option1 == value1 [more conditions...]).
ADD_PHASE("classhierarchy", true)
ADD_PHASE("vtableanalysis", true)
ADD_PHASE("reflectionanalysis", true)
ADD_PHASE("gencheckcast", true)
ADD_PHASE("javaintrnlowering", true)
// mephase begin
ADD_PHASE("ssatab", true)
ADD_PHASE("aliasclass", true)
ADD_PHASE("ssa", true)
ADD_PHASE("analyzerc", true)
ADD_PHASE("rclowering", true)
ADD_PHASE("emit", true)
// mephase end
ADD_PHASE("GenNativeStubFunc", true)
ADD_PHASE("clinit", true)
ADD_PHASE("VtableImpl", true)
ADD_PHASE("javaehlower", true)
ADD_PHASE("MUIDReplacement", true)
The first parameter is the phase name, and the second parameter is the condition. All existing phases are enabled by default. For user-defined phases, control conditions can be added.
With the ProcessMpl2mplAndMePhases method, the phases.def file can be included and added to MapleVector through a macro.
#include "../defs/phases.def"
#define ADD_PHASE(name, condition) \
if ((condition)) { \
phases.push_back(string(name)); \
}
The InitPhases interface decomposes the added phase into the phase manager set of InterleavedManager.
void DriverRunner::InitPhases(InterleavedManager &mgr, vector<string> &phases) const {
if (phases.empty()) {
return;
}
const PhaseManager *curManager = nullptr;
vector<string> curPhases;
for (string phase : phases) {
auto temp = mgr.GetSupportPhaseManager(phase);
if (temp != nullptr) {
if (temp != curManager) {
AddPhases(mgr, curPhases, curManager);
curManager = temp;
curPhases.clear();
}
AddPhase(curPhases, phase, curManager);
}
}
AddPhases(mgr, curPhases, curManager);
}
GetSupportPhaseManager is used to obtain the phase manager corresponding to the current phase.
Summary:
With the preceding framework, perform the following steps to apply a defined phase to the system.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。