This action will force synchronization from 方舟编译器/OpenArkCompiler, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
方舟编译器包含了一系列优化措施,并以phase的形式进行管理。本文将以中端的优化为例,介绍phase的设计和使用,以及如何自定义phase。
中端主要包含两大类phase:ModulePhase和MeFuncPhase,都继承自Phase类。phase类最重要的是Run方法,根据是否要做分析分为两个重载。
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);
}
所以,当添加一个新的phase的时候,必须要实现其中至少一个Run方法,并重写PhaseName方法返回名字。以rclowering作为一个例子:
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负责phase的创建、管理和运行。与phase对应,有ModulePhaseManager和MeFuncPhaseManager两类。 PhaseManager首先注册其所有支持的phase,然后使用者就可以根据需要通过add phase接口添加期望使用的phase。
1.注册phase
以MeFuncPhaseManager为例,其通过RegisterFuncPhases方法来注册。注册的phase通过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;
}
这里使用了宏的机制来实现注册,便于管理需要注册的phase,只需编辑对应的def文件即可。mephases.def部分内容如下,第一个参数是id,第二个是phase类名。
FUNCAPHASE(MeFuncPhase_SSATAB, MeDoSSATab)
FUNCAPHASE(MeFuncPhase_ALIASCLASS, MeDoAliasClass)
FUNCAPHASE(MeFuncPhase_SSA, MeDoSSA)
对于上面举例的rclowering phase,支持它只需添加如下一行即可:
FUNCTPHASE(MeFuncPhase_RCLOWERING, MeDoRCLowering)
2.添加phase
子类phase manager都提供了各自添加phase的接口,这些接口对输入进行处理后最终会调用基类PhaseManager的AddPhase方法。
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;
}
}
...
添加的phase通过MapleVector来进行管理。
使用者除了可以使用上面的方式自行添加phase外,还可以借助InterleavedManager和DriverRunner组成的框架对phase进行更有效的管理。
1.InterleavedManager
InterleavedManager负责phase manager的创建、管理和运行。通过调用AddPhases接口,它将创建一个对应类型的phase manager并添加进MapleVector中, 同时该phase manager相应的phase注册、添加也会自动被触发。
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);
...
InterleavedManager的Run方法将依次运行所有管理的phase manager。
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包含了从一个mpl文件到优化结果文件的所有过程。ParseInput方法负责解析mpl文件。ProcessMpl2mplAndMePhases方法通过InterleavedManager负责phase的管理和运行。
DriverRunner也是通过宏的方式来集中管理phase,在phases.def文件里添加phase,然后通过InitPhases接口来遍历所有的phase并创建对应的phase manager。
phases.def内容如下:
// 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)
第一个参数是phase名字,第二个参数是条件。现有的phase默认都是enable的,对于自定义的phase可以自行添加控制条件。
在ProcessMpl2mplAndMePhases里将该phases.def文件include进来,并通过宏添加进vector里。
#include "../defs/phases.def"
#define ADD_PHASE(name, condition) \
if ((condition)) { \
phases.push_back(string(name)); \
}
InitPhases方法会将添加的phase拆解到InterleavedManager的phase manager集合里。
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用来获取当前phase对应的phase manager。
总结一下,phase涉及到的几个关键类如下:
通过以上的框架,自定义phase只需完成如下三步便可应用到系统中:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。