方舟编译器分析六——代码分析(第四篇)
作者:互联网
2021SC@SDUSC
老规矩,先贴上官方源码:
今天还是研究分析该编译器代码的bb部分本次研究的是cpp文件的下半部分。具体链接如下所示:
src/mapleall/maple_me/src/bb.cpp · 方舟编译器/OpenArkCompiler - Gitee.com
src/mapleall/maple_me/include/bb.h · 方舟编译器/OpenArkCompiler - Gitee.com
上期博客分析了bb代码的上半部分,代码量实在有些大,我就在此分析下半部分。
这部分代码可以获得pred的索引位置:
int BB::GetPredIndex(const BB &predBB) {
int i = 0;
while (i < pred.size()) {
if (pred[i] == &predBB) {
break;
}
++i;
}
if (i == pred.size()) {
// bb not in the vector
return -1;
}
return i;
}
向StmtNode中添加指定数据:
// add stmtnode to bb and update first_stmt_ and last_stmt_
void BB::AddStmtNode(StmtNode *stmt) {
CHECK_FATAL(stmt != nullptr, "null ptr check");
stmtNodeList.push_back(stmt);
}
如果 bb 只包含评论以外的一个 stmt,则返回该 stmt ,否则返回 nullptr :
StmtNode *BB::GetTheOnlyStmtNode() {
StmtNode *onlyStmtNode = nullptr;
for (auto &stmtNode : stmtNodeList) {
if (stmtNode.GetOpCode() == OP_comment) {
continue;
}
if (onlyStmtNode != nullptr) {
return nullptr;
}
onlyStmtNode = &stmtNode;
}
return onlyStmtNode;
}
移除指定stmtNode中的数据(如果其不在bb中则会出现错误):
void BB::RemoveStmtNode(StmtNode *stmt) {
CHECK_FATAL(stmt != nullptr, "null ptr check");
stmtNodeList.erase(StmtNodes::iterator(stmt));
}
插入、替换和移除最后一个节点:
void BB::InsertStmtBefore(StmtNode *stmt, StmtNode *newStmt) {
CHECK_FATAL(newStmt != nullptr, "null ptr check");
CHECK_FATAL(stmt != nullptr, "null ptr check");
stmtNodeList.insert(stmt, newStmt);
}
void BB::ReplaceStmt(StmtNode *stmt, StmtNode *newStmt) {
InsertStmtBefore(stmt, newStmt);
RemoveStmtNode(stmt);
}
// delete last_stmt_ and update
void BB::RemoveLastStmt() {
stmtNodeList.pop_back();
}
用新的bb替换pred:
void BB::ReplacePred(const BB *old, BB *newPred) {
ASSERT((old != nullptr && newPred != nullptr), "Nullptr check.");
ASSERT((old->IsInList(pred) && IsInList(old->succ)), "Nullptr check.");
for (auto &predElement : pred) {
if (predElement == old) {
predElement->RemoveBBFromSucc(*this);
if (IsInList(newPred->succ)){
RemoveBBFromPred(*predElement, true);
} else {
newPred->succ.push_back(this);
predElement = newPred;
}
break;
}
}
}
移除全部pred:
void BB::MoveAllPredToSucc(BB *newSucc, BB *commonEntry) {
ASSERT_NOT_NULL(newSucc);
if (GetAttributes(kBBAttrIsEntry)) {
ASSERT(IsSuccBB(*commonEntry), "BB is not in commonEntry's successors, but it is set kBBAttrIsEntry");
commonEntry->RemoveEntry(*this);
commonEntry->AddEntry(*newSucc);
newSucc->SetAttributes(kBBAttrIsEntry);
} else {
while (!GetPred().empty()) {
BB *firstPred = GetPred(0);
if (IsSuccBB(*firstPred)) { // avoid replacing twice
firstPred->ReplaceSucc(this, newSucc, true); // firstPred will be removed from this->pred
}
}
}
}
替换succ:
void BB::ReplaceSucc(const BB *old, BB *newSucc, bool updatePhi) {
ASSERT((old != nullptr && newSucc != nullptr), "Nullptr check.");
ASSERT((old->IsInList(succ) && IsInList(old->pred)), "Nullptr check.");
for (auto &succElement : succ) {
if (succElement == old) {
succElement->RemoveBBFromPred(*this, updatePhi);
if (IsInList(newSucc->pred)) {
RemoveBBFromSucc(*succElement);
} else {
newSucc->pred.push_back(this);
succElement = newSucc;
}
break;
}
}
}
这次的分析差不多就到这里了,我的水平也不高,难以说的非常透彻,希望有大佬能够指正。
标签:old,BB,pred,newSucc,nullptr,stmt,编译器,方舟,第四篇 来源: https://blog.csdn.net/weixin_46915587/article/details/120978576