diff --git a/src/bin/maple b/src/bin/maple index 146010e30c1c80f697f8c7ad8c5797742d7b2e55..1d4d000c451ea1ec64a0fcea30710c3c6046e86e 100755 Binary files a/src/bin/maple and b/src/bin/maple differ diff --git a/src/maple_ir/include/metadata_layout.h b/src/maple_ir/include/metadata_layout.h index a26751599bb58f79ac2318a4b3ff3f31be8faa75..6d0982f2d28a1e2bf77f8c6ccff5f595043c16e8 100644 --- a/src/maple_ir/include/metadata_layout.h +++ b/src/maple_ir/include/metadata_layout.h @@ -139,7 +139,7 @@ struct GctibRef { // MByteRef is self-encoded/decoded and aligned to 1 byte. // Unlike DataRef, the format of MByteRef is determined by its value. struct MByteRef { - void* refVal; // initializer prefers this field to be a pointer + void *refVal; // initializer prefers this field to be a pointer enum { kBiasBitPosition = sizeof(refVal) * 8 - 4, // the most significant 3 bits }; diff --git a/src/maple_me/BUILD.gn b/src/maple_me/BUILD.gn index a9a2bde706d2d4c31375da21af8ad10b315fc827..46d2c18c496cb95e42ac1d3096f9d823a515310a 100644 --- a/src/maple_me/BUILD.gn +++ b/src/maple_me/BUILD.gn @@ -12,12 +12,14 @@ include_directories = [ src_libmplme = [ "src/dse.cpp", + "src/hdse.cpp", "src/prop.cpp", "src/me_alias_class.cpp", "src/me_bb_layout.cpp", "src/me_bypath_eh.cpp", "src/me_cfg.cpp", "src/me_dse.cpp", + "src/me_hdse.cpp", "src/me_dominance.cpp", "src/me_emit.cpp", "src/me_function.cpp", diff --git a/src/maple_me/include/hdse.h b/src/maple_me/include/hdse.h new file mode 100644 index 0000000000000000000000000000000000000000..59bbf7b7c81523849b44a5d1f8997a585d0ae6f0 --- /dev/null +++ b/src/maple_me/include/hdse.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#ifndef MAPLE_ME_INCLUDE_HDSE_H +#define MAPLE_ME_INCLUDE_HDSE_H +#include "bb.h" +#include "irmap.h" +#include "dominance.h" + +namespace maple { +class MeIRMap; +class HDSE { + public: + HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, SSATab &stab, + Dominance &pDom, IRMap &map, bool enabledDebug = false) + : hdseDebug(enabledDebug), + mirModule(mod), + bbVec(bbVec), + commonEntryBB(commonEntryBB), + commonExitBB(commonExitBB), + ssaTab(stab), + postDom(pDom), + irMap(map), + bbRequired(bbVec.size(), false) {} + + virtual ~HDSE() = default; + + void DoHDSE(); + void InvokeHDSEUpdateLive(); + + protected: + bool hdseDebug; + bool hdseKeepRef = false; + + private: + void DseInit(); + void MarkSpecialStmtRequired(); + void PropagateUseLive(MeExpr &meExpr); + void RemoveNotRequiredStmtsInBB(BB &bb); + template + void MarkPhiRequired(VarOrRegPhiNode &mePhiNode); + void MarkMuListRequired(MapleMap &); + void MarkChiNodeRequired(ChiMeNode &chiNode); + bool ExprNonDeletable(MeExpr &expr); + bool StmtMustRequired(const MeStmt &stmt, BB &bb); + void MarkStmtRequired(MeStmt &stmt); + bool HasNonDeletableExpr(const MeStmt &stmt); + void MarkStmtUseLive(MeStmt &meStmt); + void MarkSingleUseLive(MeExpr &meExpr); + void MarkControlDependenceLive(BB &bb); + void MarkLastBranchStmtInBBRequired(BB &bb); + void MarkLastStmtInPDomBBRequired(BB &bb); + void MarkLastUnconditionalGotoInPredBBRequired(BB &bb); + void MarkVarDefByStmt(VarMeExpr &varMeExpr); + void MarkRegDefByStmt(RegMeExpr ®MeExpr); + + bool IsExprNeeded(const MeExpr *meExpr) { + return exprLive.at(meExpr->GetExprID()); + } + void SetExprNeeded(const MeExpr *meExpr) { + exprLive.at(meExpr->GetExprID()) = true; + } + + void PropagateLive() { + while (!worklist.empty()) { + MeExpr *meExpr = worklist.front(); + worklist.pop_front(); + PropagateUseLive(*meExpr); + } + } + + void RemoveNotRequiredStmts() { + for (auto *bb : bbVec) { + if (bb == nullptr) { + continue; + } + RemoveNotRequiredStmtsInBB(*bb); + } + } + + MIRModule &mirModule; + MapleVector bbVec; + BB &commonEntryBB; + BB &commonExitBB; + SSATab &ssaTab; + Dominance &postDom; + IRMap &irMap; + std::vector bbRequired; + std::vector exprLive; + std::forward_list worklist; +}; +} // namespace maple +#endif // MAPLE_ME_INCLUDE_HDSE_H diff --git a/src/maple_me/include/me_hdse.h b/src/maple_me/include/me_hdse.h new file mode 100644 index 0000000000000000000000000000000000000000..4d3baa2045aec1867a8301d290295bcdd9154eae --- /dev/null +++ b/src/maple_me/include/me_hdse.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#ifndef MAPLE_ME_INCLUDE_MEHDSE_H +#define MAPLE_ME_INCLUDE_MEHDSE_H +#include +#include "bb.h" +#include "me_cfg.h" +#include "me_phase.h" +#include "me_option.h" +#include "me_dominance.h" +#include "hdse.h" +namespace maple { +class MeHDSE : public HDSE { + public: + MeHDSE(MeFunction &f, Dominance &pdom, IRMap &map, bool enabledDebug) + : HDSE(f.GetMIRModule(), f.GetAllBBs(), *f.GetCommonEntryBB(), *f.GetCommonExitBB(), *f.GetMeSSATab(), + pdom, map, enabledDebug) {} + + virtual ~MeHDSE() = default; + void RunHDSE(); +}; + +class MeDoHDSE : public MeFuncPhase { + public: + explicit MeDoHDSE(MePhaseID id) : MeFuncPhase(id) {} + + virtual ~MeDoHDSE() = default; + void MakeEmptyTrysUnreachable(MeFunction &func); + AnalysisResult *Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) override; + std::string PhaseName() const override { + return "hdse"; + } +}; +} // namespace maple +#endif // MAPLE_ME_INCLUDE_MEHDSE_H diff --git a/src/maple_me/include/me_option.h b/src/maple_me/include/me_option.h index ac799553e1cfc0c404aed20c3602effb58870689..55788e0e565bf0af5814b3f33bef3044c86be6ba 100644 --- a/src/maple_me/include/me_option.h +++ b/src/maple_me/include/me_option.h @@ -62,6 +62,7 @@ class MeOption { static bool stmtNum; static uint8 optLevel; static bool ignoreIPA; + static bool dseKeepRef; static bool lessThrowAlias; static bool regreadAtReturn; static bool propBase; diff --git a/src/maple_me/src/hdse.cpp b/src/maple_me/src/hdse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a541be3185550dfaa1a5224d8de35d3d1ac797a --- /dev/null +++ b/src/maple_me/src/hdse.cpp @@ -0,0 +1,455 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#include "hdse.h" +#include +#include "ssa_mir_nodes.h" +#include "ver_symbol.h" +#include "irmap.h" +#include "opcode_info.h" +#include "mir_preg.h" +#include "utils.h" + +// This phase do dead store elimination. This optimization is done on a per-SSA +// version basis. As a result, an overall criterion is that the SSA version must +// not have appeared as phi operand; +// This optimization consider all stmt are not needed at first. +// The work steps as follow: +// 1. mark all stmt are not needed. init an empty worklist to put live node. +// 2. mark some special stmts which has side effect as needed, such as +// return/eh/call and some assigned stmts who have volatile fileds and so on. +// Put all operands and mayUse nodes of the needed stmt into worklist. +// 3. For the nodes in worklist mark the def stmt as needed just as step 2 and +// pop the node from the worklist. +// 4. Repeat step 3 untile the worklist is empty. + +namespace maple { +using namespace utils; + +void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { + for (auto &meStmt : bb.GetMeStmts()) { + if (!meStmt.GetIsLive()) { + if (hdseDebug) { + mirModule.GetOut() << "========== HSSA DSE is deleting this stmt: "; + meStmt.Dump(&irMap); + } + if (meStmt.GetOp() != OP_dassign && (meStmt.IsCondBr() || meStmt.GetOp() == OP_switch)) { + // update CFG + while (bb.GetSucc().size() != 1) { + BB *succbb = bb.GetSucc().back(); + succbb->RemoveBBFromPred(&bb); + bb.GetSucc().pop_back(); + } + bb.SetKind(kBBFallthru); + } + bb.RemoveMeStmt(&meStmt); + } + } +} + +void HDSE::MarkMuListRequired(MapleMap &muList) { + for (auto &pair : muList) { + worklist.push_front(pair.second); + } +} + +void HDSE::MarkChiNodeRequired(ChiMeNode &chiNode) { + if (chiNode.GetIsLive()) { + return; + } + chiNode.SetIsLive(true); + worklist.push_front(chiNode.GetRHS()); + MeStmt *meStmt = chiNode.GetBase(); + MarkStmtRequired(*meStmt); +} + +template +void HDSE::MarkPhiRequired(VarOrRegPhiNode &mePhiNode) { + if (mePhiNode.GetIsLive()) { + return; + } + mePhiNode.SetIsLive(true); + for (auto *meExpr : mePhiNode.GetOpnds()) { + if (meExpr != nullptr) { + MarkSingleUseLive(*meExpr); + } + } + MarkControlDependenceLive(*mePhiNode.GetDefBB()); +} + +void HDSE::MarkVarDefByStmt(VarMeExpr &varExpr) { + switch (varExpr.GetDefBy()) { + case kDefByNo: + break; + case kDefByStmt: { + auto *defStmt = varExpr.GetDefStmt(); + if (defStmt != nullptr) { + MarkStmtRequired(*defStmt); + } + break; + } + case kDefByPhi: { + MarkPhiRequired(varExpr.GetDefPhi()); + break; + } + case kDefByChi: { + auto *defChi = &varExpr.GetDefChi(); + if (defChi != nullptr) { + MarkChiNodeRequired(*defChi); + } + break; + } + case kDefByMustDef: { + auto *mustDef = &varExpr.GetDefMustDef(); + if (!mustDef->GetIsLive()) { + mustDef->SetIsLive(true); + MarkStmtRequired(*mustDef->GetBase()); + } + break; + } + default: + ASSERT(false, "var defined wrong"); + break; + } +} + +void HDSE::MarkRegDefByStmt(RegMeExpr ®MeExpr) { + PregIdx regIdx = regMeExpr.GetRegIdx(); + if (regIdx == -kSregRetval0) { + if (regMeExpr.GetDefStmt()) { + MarkStmtRequired(*regMeExpr.GetDefStmt()); + } + return; + } + switch (regMeExpr.GetDefBy()) { + case kDefByNo: + break; + case kDefByStmt: { + auto *defStmt = regMeExpr.GetDefStmt(); + if (defStmt != nullptr) { + MarkStmtRequired(*defStmt); + } + break; + } + case kDefByPhi: + MarkPhiRequired(regMeExpr.GetDefPhi()); + break; + case kDefByMustDef: { + MustDefMeNode *mustDef = ®MeExpr.GetDefMustDef(); + if (!mustDef->GetIsLive()) { + mustDef->SetIsLive(true); + MarkStmtRequired(*mustDef->GetBase()); + } + break; + } + default: + ASSERT(false, "MarkRegDefByStmt unexpected defBy value"); + break; + } +} + +void HDSE::PropagateUseLive(MeExpr &meExpr) { + switch (meExpr.GetMeOp()) { + case kMeOpVar: { + auto &varMeExpr = static_cast(meExpr); + MarkVarDefByStmt(varMeExpr); + return; + } + case kMeOpReg: { + auto ®MeExpr = static_cast(meExpr); + MarkRegDefByStmt(regMeExpr); + return; + } + default: { + ASSERT(false, "MeOp ERROR"); + return; + } + } +} + +bool HDSE::ExprNonDeletable(MeExpr &meExpr) { + if (kOpcodeInfo.HasSideEffect(meExpr.GetOp())) { + return true; + } + switch (meExpr.GetMeOp()) { + case kMeOpReg: { + auto ®MeExpr = static_cast(meExpr); + return (regMeExpr.GetRegIdx() == -kSregThrownval); + } + case kMeOpVar: { + auto &varMeExpr = static_cast(meExpr); + return varMeExpr.IsVolatile(ssaTab); + } + case kMeOpIvar: { + auto &opIvar = static_cast(meExpr); + return opIvar.IsVolatile() || ExprNonDeletable(*opIvar.GetBase()); + } + case kMeOpOp: { + if (meExpr.GetOp() == OP_gcmallocjarray) { + return true; + } + } + case kMeOpNary: { + auto &opNary = static_cast(meExpr); + if (meExpr.GetOp() == OP_intrinsicop) { + IntrinDesc *intrinDesc = &IntrinDesc::intrinTable[opNary.GetIntrinsic()]; + return (!intrinDesc->HasNoSideEffect()); + } + } + default: + break; + } + for (size_t i = 0; i != meExpr.GetNumOpnds(); ++i) { + if (ExprNonDeletable(*meExpr.GetOpnd(i))) { + return true; + } + } + return false; +} + +bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) { + Opcode op = meStmt.GetOp(); + switch (op) { + case OP_dassign: { + auto &dasgn = static_cast(meStmt); + VarMeExpr *varMeExpr = dasgn.GetVarLHS(); + return (varMeExpr && varMeExpr->IsVolatile(ssaTab)) || ExprNonDeletable(*dasgn.GetRHS()) || + (hdseKeepRef && dasgn.Propagated()) || dasgn.GetWasMayDassign(); + } + case OP_regassign: { + auto &rasgn = static_cast(meStmt); + return ExprNonDeletable(*rasgn.GetRHS()); + } + case OP_maydassign: + return true; + case OP_iassign: { + auto &iasgn = static_cast(meStmt); + auto &ivarMeExpr = static_cast(*iasgn.GetLHSVal()); + return ivarMeExpr.IsVolatile() || ivarMeExpr.IsFinal() || + ExprNonDeletable(*iasgn.GetLHSVal()->GetBase()) || ExprNonDeletable(*iasgn.GetRHS()); + } + default: + return false; + } +} + +void HDSE::MarkLastUnconditionalGotoInPredBBRequired(BB &bb) { + for (auto predIt = bb.GetPred().begin(); predIt != bb.GetPred().end(); ++predIt) { + BB *predBB = *predIt; + if (predBB == &bb || predBB->GetMeStmts().empty()) { + continue; + } + auto &lastStmt = predBB->GetMeStmts().back(); + if (!lastStmt.GetIsLive() && lastStmt.GetOp() == OP_goto) { + MarkStmtRequired(lastStmt); + } + } +} + +void HDSE::MarkLastStmtInPDomBBRequired(BB &bb) { + CHECK(bb.GetBBId() < postDom.GetPdomFrontierSize(), "index out of range in HDSE::MarkLastStmtInPDomBBRequired"); + for (BBId cdBBId : postDom.GetPdomFrontierItem(bb.GetBBId())) { + BB *cdBB = bbVec[cdBBId]; + CHECK_FATAL(cdBB != nullptr, "cdBB is null in HDSE::MarkLastStmtInPDomBBRequired"); + if (cdBB == &bb || cdBB->IsMeStmtEmpty()) { + continue; + } + auto &lastStmt = cdBB->GetMeStmts().back(); + Opcode op = lastStmt.GetOp(); + CHECK_FATAL((lastStmt.IsCondBr() || op == OP_switch || op == OP_retsub || op == OP_throw || + cdBB->GetAttributes(kBBAttrIsTry) || cdBB->GetAttributes(kBBAttrWontExit)), + "HDSE::MarkLastStmtInPDomBBRequired: control dependent on unexpected statement"); + if ((IsBranch(op) || op == OP_retsub || op == OP_throw)) { + MarkStmtRequired(lastStmt); + } + } +} + +void HDSE::MarkLastBranchStmtInBBRequired(BB &bb) { + auto &meStmts = bb.GetMeStmts(); + if (!meStmts.empty()) { + auto &lastStmt = meStmts.back(); + Opcode op = lastStmt.GetOp(); + if (IsBranch(op)) { + MarkStmtRequired(lastStmt); + } + } +} + +void HDSE::MarkControlDependenceLive(BB &bb) { + if (bbRequired[bb.GetBBId()]) { + return; + } + bbRequired[bb.GetBBId()] = true; + + MarkLastBranchStmtInBBRequired(bb); + MarkLastStmtInPDomBBRequired(bb); + MarkLastUnconditionalGotoInPredBBRequired(bb); +} + +void HDSE::MarkSingleUseLive(MeExpr &meExpr) { + if (IsExprNeeded(&meExpr)) { + return; + } + SetExprNeeded(&meExpr); + MeExprOp meOp = meExpr.GetMeOp(); + switch (meOp) { + case kMeOpVar: + case kMeOpReg: { + worklist.push_front(&meExpr); + break; + } + case kMeOpIvar: { + auto *base = static_cast(meExpr).GetBase(); + if (base != nullptr) { + MarkSingleUseLive(*base); + } + break; + } + default: + break; + } + + for (size_t i = 0; i != meExpr.GetNumOpnds(); ++i) { + MeExpr *operand = meExpr.GetOpnd(i); + if (operand != nullptr) { + MarkSingleUseLive(*operand); + } + } +} + +void HDSE::MarkStmtUseLive(MeStmt &meStmt) { + // mark single use + for (size_t i = 0; i < meStmt.NumMeStmtOpnds(); ++i) { + auto *operand = meStmt.GetOpnd(i); + if (operand != nullptr) { + MarkSingleUseLive(*operand); + } + } + + // mark MuList + auto *muList = meStmt.GetMuList(); + if (muList != nullptr) { + MarkMuListRequired(*muList); + } +} + +void HDSE::MarkStmtRequired(MeStmt &meStmt) { + if (meStmt.GetIsLive()) { + return; + } + meStmt.SetIsLive(true); + + if (meStmt.GetOp() == OP_comment) { + return; + } + + // mark use + MarkStmtUseLive(meStmt); + + // markBB + MarkControlDependenceLive(*meStmt.GetBB()); +} + +bool HDSE::StmtMustRequired(const MeStmt &meStmt, BB &bb) { + Opcode op = meStmt.GetOp(); + // special opcode cannot be eliminated + if (IsStmtMustRequire(op) || op == OP_comment) { + return true; + } + // control flow in an infinite loop cannot be eliminated + if (ControlFlowInInfiniteLoop(bb, op)) { + return true; + } + // if stmt has not deletable expr + if (HasNonDeletableExpr(meStmt)) { + return true; + } + return false; +} + +void HDSE::MarkSpecialStmtRequired() { + for (auto *bb : bbVec) { + if (bb == nullptr) { + continue; + } + auto &meStmtNodes = bb->GetMeStmts(); + for (auto itStmt = meStmtNodes.rbegin(); itStmt != meStmtNodes.rend(); ++itStmt) { + MeStmt *pStmt = to_ptr(itStmt); + if (pStmt->GetIsLive()) { + continue; + } + if (StmtMustRequired(*pStmt, *bb)) { + MarkStmtRequired(*pStmt); + } + } + } +} + +void HDSE::DseInit() { + // Init bb's required flag + if (&commonEntryBB != *bbVec.begin()) { + bbRequired[commonEntryBB.GetBBId()] = true; + } + if (&commonExitBB != *bbVec.end()) { + bbRequired[commonExitBB.GetBBId()] = true; + } + // Init all MeExpr to be dead; + exprLive.resize(irMap.GetExprID(), false); + + for (auto *bb : bbVec) { + if (bb == nullptr) { + continue; + } + // mark phi nodes dead + for (std::pair varPhiPair : bb->GetMevarPhiList()) { + varPhiPair.second->SetIsLive(false); + } + for (std::pair regPhiPair : bb->GetMeRegPhiList()) { + regPhiPair.second->SetIsLive(false); + } + for (auto &stmt : bb->GetMeStmts()) { + // mark stmt dead + stmt.SetIsLive(false); + // mark chi nodes dead + MapleMap *chiList = stmt.GetChiList(); + if (chiList != nullptr) { + for (std::pair pair : *chiList) { + pair.second->SetIsLive(false); + } + } + // mark mustDef nodes dead + if (kOpcodeInfo.IsCallAssigned(stmt.GetOp())) { + MapleVector *mustDefList = stmt.GetMustDefList(); + for (MustDefMeNode &mustDef : *mustDefList) { + mustDef.SetIsLive(false); + } + } + } + } +} + +void HDSE::InvokeHDSEUpdateLive() { + DseInit(); + MarkSpecialStmtRequired(); + PropagateLive(); +} + +void HDSE::DoHDSE() { + DseInit(); + MarkSpecialStmtRequired(); + PropagateLive(); + RemoveNotRequiredStmts(); +} +} // namespace maple diff --git a/src/maple_me/src/me_dse.cpp b/src/maple_me/src/me_dse.cpp index 1c8d889511e90ea478d78ddcc6a608f69499aa41..cd0144645a69603bf670e9767a54625be5b09fa5 100644 --- a/src/maple_me/src/me_dse.cpp +++ b/src/maple_me/src/me_dse.cpp @@ -61,9 +61,9 @@ void MeDSE::RunDSE() { AnalysisResult *MeDoDSE::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) { CHECK_NULL_FATAL(func); - auto *pdom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); - CHECK_NULL_FATAL(pdom); - MeDSE dse(func, pdom, DEBUGFUNC(func)); + auto *postDom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); + CHECK_NULL_FATAL(postDom); + MeDSE dse(func, postDom, DEBUGFUNC(func)); dse.RunDSE(); func->Verify(); // cfg change , invalid results in MeFuncResultMgr diff --git a/src/maple_me/src/me_hdse.cpp b/src/maple_me/src/me_hdse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6db84071708f54ef4e14ef0b2ca23720d8bae8b9 --- /dev/null +++ b/src/maple_me/src/me_hdse.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#include "me_hdse.h" +#include +#include "ssa_mir_nodes.h" +#include "ver_symbol.h" +#include "dominance.h" +#include "me_irmap.h" +#include "me_ssa.h" +#include "hdse.h" +namespace maple { +void MeDoHDSE::MakeEmptyTrysUnreachable(MeFunction &func) { + auto eIt = func.valid_end(); + for (auto bIt = func.valid_begin(); bIt != eIt; ++bIt) { + BB *tryBB = *bIt; + // get next valid bb + auto endTryIt = bIt; + if (++endTryIt == eIt) { + break; + } + BB *endTry = *endTryIt; + auto &meStmts = tryBB->GetMeStmts(); + if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && + meStmts.front().GetOp() == OP_try && tryBB->GetMevarPhiList().empty() && + tryBB->GetMeRegPhiList().empty() && endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { + // we found a try BB followed by an empty endtry BB + BB *targetBB = endTry->GetSucc(0); + std::vector toDeleteTryPreds; + int32 indexOfEndTryInTargetBBPreds = -1; + for (auto *tryPred : tryBB->GetPred()) { + MapleVector &allSucc = tryPred->GetSucc(); + toDeleteTryPreds.push_back(tryPred); + // replace tryBB in the pred's succ list by targetbb + size_t j = 0; + for (; j < allSucc.size(); ++j) { + if (allSucc[j] == tryBB) { + break; + } + } + CHECK_FATAL(j != allSucc.size(), + "MakeEmptyTrysUnreachable: cannot find tryBB among the succ list of one of its pred BB"); + allSucc[j] = targetBB; + // update targetbb's predecessors + size_t k = 0; + for (; k < targetBB->GetPred().size(); ++k) { + if (targetBB->GetPred(k) == endTry) { + indexOfEndTryInTargetBBPreds = k; + } else if (targetBB->GetPred(k) == tryPred) { + break; + } + } + if (k == targetBB->GetPred().size()) { + targetBB->GetPred().push_back(tryPred); + CHECK_FATAL(indexOfEndTryInTargetBBPreds != -1, "MakeEmptyTrysUnreachable: processing error"); + // push additional phi operand for each phi at targetbb + auto phiIter = targetBB->GetMevarPhiList().begin(); + for (; phiIter != targetBB->GetMevarPhiList().end(); ++phiIter) { + MeVarPhiNode *meVarPhi = phiIter->second; + meVarPhi->GetOpnds().push_back(meVarPhi->GetOpnds()[indexOfEndTryInTargetBBPreds]); + } + } + // if needed, update branch label + MeStmt *br = to_ptr(tryPred->GetMeStmts().rbegin()); + if (br != nullptr) { + if (br->IsCondBr()) { + if (static_cast(br)->GetOffset() == tryBB->GetBBLabel()) { + LabelIdx label = func.GetOrCreateBBLabel(*targetBB); + static_cast(br)->SetOffset(label); + } + } else if (br->GetOp() == OP_goto) { + LabelIdx label = func.GetOrCreateBBLabel(*targetBB); + ASSERT(static_cast(br)->GetOffset() == tryBB->GetBBLabel(), "Wrong label"); + static_cast(br)->SetOffset(label); + } else if (br->GetOp() == OP_multiway || br->GetOp() == OP_rangegoto) { + CHECK_FATAL(false, "OP_multiway and OP_rangegoto are not supported"); + } else if (br->GetOp() == OP_switch) { + LabelIdx label = func.GetOrCreateBBLabel(*targetBB); + auto *switchNode = static_cast(br); + if (switchNode->GetDefaultLabel() == tryBB->GetBBLabel()) { + switchNode->SetDefaultLabel(label); + } + for (size_t m = 0; m < switchNode->GetSwitchTable().size(); m++) { + if (switchNode->GetSwitchTable()[m].second == tryBB->GetBBLabel()) { + switchNode->SetCaseLabel(m, label); + } + } + } + } + } + // tryBB has no phis, no need to update them + for (auto bb : toDeleteTryPreds) { + bb->RemoveBBFromVector(tryBB->GetPred()); + } + } + } +} + +void MeHDSE::RunHDSE() { + hdseKeepRef = MeOption::dseKeepRef; + DoHDSE(); +} + +AnalysisResult *MeDoHDSE::Run(MeFunction *func, MeFuncResultMgr *m, ModuleResultMgr *mrm) { + auto *postDom = static_cast(m->GetAnalysisResult(MeFuncPhase_DOMINANCE, func)); + CHECK_NULL_FATAL(postDom); + auto *hMap = static_cast(m->GetAnalysisResult(MeFuncPhase_IRMAP, func)); + CHECK_FATAL(hMap != nullptr, "hssamap is nullptr"); + MeHDSE hdse(*func, *postDom, *hMap, DEBUGFUNC(func)); + hdse.RunHDSE(); + MakeEmptyTrysUnreachable(*func); + func->GetTheCfg()->UnreachCodeAnalysis(true); + m->InvalidAnalysisResult(MeFuncPhase_DOMINANCE, func); + if (DEBUGFUNC(func)) { + LogInfo::MapleLogger() << "\n============== HDSE =============" << '\n'; + func->Dump(false); + } + return nullptr; +} +} // namespace maple diff --git a/src/maple_util/include/factory.h b/src/maple_util/include/factory.h index fda10587dd538399e58a3185e85e8146abe288ab..6e6ac23250080acf8f110d5478eb2bf9ee936819 100644 --- a/src/maple_util/include/factory.h +++ b/src/maple_util/include/factory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. @@ -20,30 +20,25 @@ namespace maple { template -class ObjectFactory { - using PtrObject = std::unique_ptr; - using CreatFunc = std::function; - using CreatorHolder = std::map; - +class ObjectFactory final { public: - using Key = TKey; - using Value = TObject; + using key_type = TKey; + using creator_type = std::function(TArgs...)>; - void Register(const TKey &key, CreatFunc func) { - auto it = objectCreator.find(key); - if (it == objectCreator.end()) { - objectCreator[key] = func; + void Register(const key_type &key, creator_type func) { + if (creator.find(key) == creator.end()) { + creator[key] = func; } } - std::unique_ptr Create(const TKey &key, TArgs... Args) const { - auto it = objectCreator.find(key); - return it == objectCreator.end() ? PtrObject() : (it->second)(Args...); + std::unique_ptr Create(const key_type &key, TArgs &&...Args) const { + auto it = creator.find(key); + return it == creator.end() ? std::unique_ptr() : (it->second)(std::forward(Args)...); } template - static PtrObject DefaultCreator(TArgs... Args) { - return PtrObject(new TObjectImpl(Args...)); + static std::unique_ptr DefaultCreator(TArgs &&...Args) { + return std::make_unique(std::forward(Args)...); } static ObjectFactory &ins() { @@ -51,50 +46,45 @@ class ObjectFactory { return factory; } - private: - ObjectFactory() = default; ObjectFactory(const ObjectFactory&) = delete; ObjectFactory &operator=(const ObjectFactory&) = delete; ObjectFactory(const ObjectFactory&&) = delete; ObjectFactory &operator=(const ObjectFactory&&) = delete; + + private: + ObjectFactory() = default; ~ObjectFactory() = default; - CreatorHolder objectCreator; + + private: + using CreatorHolder = std::map; + CreatorHolder creator; }; -template -inline bool RegisterFactoryObject() { - TFactory::ins().Register(TKey, TFactory::template DefaultCreator); - return true; +template +inline void RegisterFactoryObject() { + TFactory::ins().Register(Key, TFactory::template DefaultCreator); } template -inline auto CreateProductObject(const typename TFactory::key &Key, TArgs... Args) - -> std::unique_ptr { - return TFactory::ins().Create(Key, Args...); +inline auto CreateProductObject(const typename TFactory::key_type &key, TArgs &&...Args) { + return TFactory::ins().Create(key, std::forward(Args)...); } template -class FunctionFactory { - using FuncObject = std::function; - using FuncHolder = std::map; - +class FunctionFactory final { public: - using Key = TKey; - using Value = FuncObject; + using key_type = TKey; + using creator_type = std::function; - void Register(const TKey &key, FuncObject func) { - auto it = funcCreator.find(key); - if (it == funcCreator.end()) { - funcCreator[key] = func; + void Register(const key_type &key, creator_type func) { + if (creator.find(key) == creator.end()) { + creator[key] = func; } } - FuncObject Create(const TKey &key) const { - auto it = funcCreator.find(key); - if (it == funcCreator.end()) { - return nullptr; - } - return it->second; + creator_type Create(const key_type &key) const { + auto it = creator.find(key); + return it == creator.end() ? nullptr : it->second; } static FunctionFactory &ins() { @@ -102,23 +92,27 @@ class FunctionFactory { return factory; } - private: - FunctionFactory() = default; FunctionFactory(const FunctionFactory&) = delete; FunctionFactory &operator=(const FunctionFactory&) = delete; FunctionFactory(const FunctionFactory&&) = delete; FunctionFactory &operator=(const FunctionFactory&&) = delete; + + private: + FunctionFactory() = default; ~FunctionFactory() = default; - FuncHolder funcCreator; + + private: + using CreatorHolder = std::map; + CreatorHolder creator; }; template -inline void RegisterFactoryFunction(const typename TFactory::Key &key, typename TFactory::Value func) { +inline void RegisterFactoryFunction(const typename TFactory::key_type &key, typename TFactory::creator_type func) { TFactory::ins().Register(key, func); } template -inline auto CreateProductFunction(const typename TFactory::Key &key) -> typename TFactory::Value { +inline auto CreateProductFunction(const typename TFactory::key_type &key) { return TFactory::ins().Create(key); } } // namespace maple diff --git a/src/maple_util/include/safe_cast.h b/src/maple_util/include/safe_cast.h index d69692f52ed649c161a63db1934b1c7c57b25775..19d9e40e379eee5bae1d7b78ed23c25b4c24eae2 100644 --- a/src/maple_util/include/safe_cast.h +++ b/src/maple_util/include/safe_cast.h @@ -25,7 +25,7 @@ struct safe_cast_condition : std::false_type {}; template <> \ struct safe_cast_condition : std::true_type { \ template \ - static inline bool DoIt(const FromT &from) { \ + static inline bool DoIt(const FromT &from) { \ return (condition); \ } \ } diff --git a/src/maple_util/include/safe_ptr.h b/src/maple_util/include/safe_ptr.h index 346b7f01e48862cd64ca3c511f5f3a3a77dc61f1..42f970458c5b54881a0e925ee74f64bdc932eca3 100644 --- a/src/maple_util/include/safe_ptr.h +++ b/src/maple_util/include/safe_ptr.h @@ -202,6 +202,11 @@ inline bool operator>=(const SafePtr &lhs, std::nullptr_t) = delete; template inline bool operator>=(std::nullptr_t, const SafePtr &rhs) = delete; +template +inline T &ToRef(SafePtr ptr) { + return *ptr; +} + }} namespace std