From cf73331fa3f12faf5c59391c79f21010b9f5ea9b Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 3 Aug 2022 14:45:17 -0700 Subject: [PATCH 1/7] Switch to using maple profile data file format; update frequences in various maple_me phases --- src/mapleall/maple_ipa/src/ipa_clone.cpp | 4 +- .../maple_ipa/src/ipa_phase_manager.cpp | 6 +- src/mapleall/maple_ir/include/mir_function.h | 8 +- src/mapleall/maple_ir/include/mir_lower.h | 2 +- src/mapleall/maple_ir/include/mir_module.h | 24 +- src/mapleall/maple_ir/src/mir_nodes.cpp | 21 +- src/mapleall/maple_me/include/bb.h | 33 +- src/mapleall/maple_me/include/hdse.h | 21 +- src/mapleall/maple_me/include/me_cfg.h | 39 +- src/mapleall/maple_me/include/me_loop_canon.h | 5 +- .../maple_me/include/me_loop_unrolling.h | 52 ++- .../maple_me/include/me_profile_use.h | 5 +- src/mapleall/maple_me/include/pme_emit.h | 2 +- src/mapleall/maple_me/src/bb.cpp | 43 ++- src/mapleall/maple_me/src/hdse.cpp | 59 ++- src/mapleall/maple_me/src/me_bb_layout.cpp | 84 ++-- src/mapleall/maple_me/src/me_cfg.cpp | 253 +++++++----- .../maple_me/src/me_critical_edge.cpp | 22 +- src/mapleall/maple_me/src/me_dse.cpp | 10 +- src/mapleall/maple_me/src/me_emit.cpp | 2 +- src/mapleall/maple_me/src/me_hdse.cpp | 23 +- src/mapleall/maple_me/src/me_loop_canon.cpp | 60 ++- .../maple_me/src/me_loop_inversion.cpp | 112 +++--- .../maple_me/src/me_loop_unrolling.cpp | 165 ++++---- src/mapleall/maple_me/src/me_profile_use.cpp | 53 +-- .../maple_me/src/me_value_range_prop.cpp | 103 +++++ src/mapleall/maple_me/src/optimizeCFG.cpp | 354 +++++++++-------- src/mapleall/maple_me/src/pme_emit.cpp | 2 +- src/mapleall/maple_util/BUILD.gn | 1 + .../maple_util/include/gcov_profile.h | 110 ------ .../maple_util/include/mpl_profdata.h | 203 ++++++++++ src/mapleall/maple_util/include/namemangler.h | 5 + src/mapleall/maple_util/src/mpl_profdata.cpp | 100 +++++ src/mapleall/maple_util/src/namemangler.cpp | 105 ++++- src/mapleall/mpl2mpl/BUILD.gn | 2 +- src/mapleall/mpl2mpl/include/gcov_parser.h | 117 ------ .../mpl2mpl/include/inline_transformer.h | 5 +- .../mpl2mpl/include/mpl_profdata_parser.h | 118 ++++++ src/mapleall/mpl2mpl/src/call_graph.cpp | 40 +- src/mapleall/mpl2mpl/src/gcov_parser.cpp | 359 ------------------ src/mapleall/mpl2mpl/src/gen_profile.cpp | 4 +- src/mapleall/mpl2mpl/src/inline.cpp | 61 +-- .../mpl2mpl/src/inline_transformer.cpp | 17 +- .../mpl2mpl/src/module_phase_manager.cpp | 4 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 204 ++++++++++ 45 files changed, 1804 insertions(+), 1218 deletions(-) delete mode 100644 src/mapleall/maple_util/include/gcov_profile.h create mode 100644 src/mapleall/maple_util/include/mpl_profdata.h create mode 100644 src/mapleall/maple_util/src/mpl_profdata.cpp delete mode 100644 src/mapleall/mpl2mpl/include/gcov_parser.h create mode 100644 src/mapleall/mpl2mpl/include/mpl_profdata_parser.h delete mode 100644 src/mapleall/mpl2mpl/src/gcov_parser.cpp create mode 100644 src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp diff --git a/src/mapleall/maple_ipa/src/ipa_clone.cpp b/src/mapleall/maple_ipa/src/ipa_clone.cpp index ff25da0c85..9b32d5cc3a 100644 --- a/src/mapleall/maple_ipa/src/ipa_clone.cpp +++ b/src/mapleall/maple_ipa/src/ipa_clone.cpp @@ -140,9 +140,9 @@ MIRFunction *IpaClone::IpaCloneFunctionWithFreq(MIRFunction &originalFunction, newFunc->SetBaseClassFuncNames(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(fullName)); newFunc->GetFuncSymbol()->SetAppearsInCode(true); newFunc->SetPuidxOrigin(newFunc->GetPuidx()); - GcovFuncInfo *origProfData = originalFunction.GetFuncProfData(); + FuncProfInfo *origProfData = originalFunction.GetFuncProfData(); auto *moduleMp = mirBuilder.GetMirModule().GetMemPool(); - GcovFuncInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), + FuncProfInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), newFunc->GetPuidx(), 0, 0); // skip checksum information newFunc->SetFuncProfData(newProfData); newProfData->SetFuncFrequency(callSiteFreq); diff --git a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp index b3fc2d7ba2..f477c8fa90 100644 --- a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp +++ b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp @@ -14,7 +14,7 @@ */ #include "ipa_phase_manager.h" #include "pme_emit.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -102,8 +102,8 @@ void IpaSccPM::GetAnalysisDependence(maple::AnalysisDep &aDep) const { aDep.AddPreserved(); aDep.AddPreserved(); if (Options::profileUse) { - aDep.AddRequired(); - aDep.AddPreserved(); + aDep.AddRequired(); + aDep.AddPreserved(); } } diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 161611f558..4b1a08acfb 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1271,13 +1271,13 @@ class MIRFunction { InlineSummary *GetOrCreateInlineSummary(); - void SetFuncProfData(GcovFuncInfo *data) { + void SetFuncProfData(FuncProfInfo *data) { funcProfData = data; } - GcovFuncInfo* GetFuncProfData() { + FuncProfInfo* GetFuncProfData() { return funcProfData; } - GcovFuncInfo* GetFuncProfData() const { + FuncProfInfo* GetFuncProfData() const { return funcProfData; } void SetStmtFreq(uint32_t stmtID, uint64_t freq) { @@ -1402,7 +1402,7 @@ class MIRFunction { uint32 nCtrs = 0; // number of counters uint64 fileLinenoChksum = 0; uint64 cfgChksum = 0; - GcovFuncInfo *funcProfData = nullptr; + FuncProfInfo *funcProfData = nullptr; InlineSummary *inlineSummary = nullptr; void DumpFlavorLoweredThanMmpl() const; MIRFuncType *ReconstructFormals(const std::vector &symbols, bool clearOldArgs); diff --git a/src/mapleall/maple_ir/include/mir_lower.h b/src/mapleall/maple_ir/include/mir_lower.h index c2261326d1..e4229aa853 100644 --- a/src/mapleall/maple_ir/include/mir_lower.h +++ b/src/mapleall/maple_ir/include/mir_lower.h @@ -142,7 +142,7 @@ class MIRLower { virtual bool InLFO() const { return false; } - GcovFuncInfo *GetFuncProfData() const { + FuncProfInfo *GetFuncProfData() const { return mirFunc->GetFuncProfData(); } void CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt) { diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index 37c54a99b3..f5965f008d 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -22,7 +22,7 @@ #include "muid.h" #include "profile.h" #include "namemangler.h" -#include "gcov_profile.h" +#include "mpl_profdata.h" #if MIR_FEATURE_FULL #include #include @@ -268,11 +268,11 @@ class MIRModule { return profile; } - GcovProfileData* GetGcovProfile() { - return gcovProfile; + MplProfileData* GetMapleProfile() { + return mplProfile; } - void SetGcovProfile(GcovProfileData* info) { - gcovProfile = info; + void SetMapleProfile(MplProfileData* info) { + mplProfile = info; } void SetSomeSymbolNeedForDecl(bool s) { @@ -341,11 +341,13 @@ class MIRModule { } std::string GetProfileDataFileName() const { - std::string profileDataFileName = fileName.substr(0, fileName.find_last_of(".")); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '.', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '-', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '/', '_'); - profileDataFileName = profileDataFileName + namemangler::kProfFileNameExt; + std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); + char *gcov_path = std::getenv("GCOV_PREFIX"); + std::string gcov_prefix = gcov_path ? gcov_path : ""; + if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { + gcov_prefix.append("/"); + } + profileDataFileName = gcov_prefix + profileDataFileName; return profileDataFileName; } @@ -710,7 +712,7 @@ class MIRModule { MapleSet symbolSet; MapleVector symbolDefOrder; Profile profile; - GcovProfileData* gcovProfile; + MplProfileData* mplProfile; bool someSymbolNeedForwDecl = false; // some symbols' addressses used in initialization std::ostream &out; diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index e8113fb657..fbdd3bae68 100644 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -686,10 +686,11 @@ void AddroflabelNode::Dump(int32 indent [[maybe_unused]]) const { void StmtNode::DumpBase(int32 indent) const { srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs - if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData() && - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) >= 0) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } PrintIndentation(indent); LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name; @@ -1329,8 +1330,10 @@ void BlockNode::Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } for (auto &stmt : GetStmtNodes()) { stmt.Dump(indent + 1); @@ -1345,8 +1348,10 @@ void LabelNode::Dump(int32 indent [[maybe_unused]]) const { } // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } LogInfo::MapleLogger() << "@" << theMIRModule->CurFunction()->GetLabelName(labelIdx) << " "; } diff --git a/src/mapleall/maple_me/include/bb.h b/src/mapleall/maple_me/include/bb.h index 24d5327261..e0c01e71e8 100644 --- a/src/mapleall/maple_me/include/bb.h +++ b/src/mapleall/maple_me/include/bb.h @@ -14,18 +14,18 @@ */ #ifndef MAPLE_ME_INCLUDE_BB_H #define MAPLE_ME_INCLUDE_BB_H -#include "utils.h" #include "mpl_number.h" -#include "ptr_list_ref.h" #include "orig_symbol.h" -#include "ver_symbol.h" +#include "ptr_list_ref.h" #include "ssa.h" +#include "utils.h" +#include "ver_symbol.h" namespace maple { -class MeStmt; // circular dependency exists, no other choice -class MePhiNode; // circular dependency exists, no other choice +class MeStmt; // circular dependency exists, no other choice +class MePhiNode; // circular dependency exists, no other choice class PiassignMeStmt; // circular dependency exists, no other choice -class IRMap; // circular dependency exists, no other choice +class IRMap; // circular dependency exists, no other choice enum BBKind { kBBUnknown, // uninitialized kBBCondGoto, @@ -406,8 +406,17 @@ class BB { ASSERT(idx >= 0 && idx <= succFreq.size(), "sanity check"); succFreq[static_cast(idx)] = freq; } + void AddSuccFreq(uint64 freq, size_t pos = UINT32_MAX) { + ASSERT((pos <= succFreq.size() || pos == UINT32_MAX), "Invalid position."); + if (pos == UINT32_MAX) { + succFreq.push_back(freq); + } else { + succFreq.insert(succFreq.begin() + pos, freq); + } + } + // update edge frequency - void UpdateEdgeFreqs(); + void UpdateEdgeFreqs(bool updateSuccFreq = true); const MapleVector &GetSucc() const { return succ; @@ -487,7 +496,7 @@ class BB { auto iter = std::find(succ.begin(), succ.end(), bb); CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d", succFreq.size(), - succ.size()); + succ.size()); const size_t idx = static_cast(std::distance(succ.begin(), iter)); succFreq[idx] = freq; } @@ -496,7 +505,7 @@ class BB { succFreq.resize(succ.size()); } - BB* GetGroup() const { + BB *GetGroup() const { return group; } @@ -524,12 +533,13 @@ class BB { int GetPredIndex(const BB &predBB) const; int GetSuccIndex(const BB &succBB) const; void RemovePhiOpnd(int index); + private: bool IsInList(const MapleVector &bbList) const; int RemoveBBFromVector(MapleVector &bbVec) const; BBId id; - LabelIdx bbLabel = 0; // the BB's label + LabelIdx bbLabel = 0; // the BB's label MapleVector pred; // predecessor list MapleVector succ; // successor list // record the edge freq from curBB to succ BB @@ -540,8 +550,10 @@ class BB { uint32 frequency = 0; BBKind kind = kBBUnknown; uint32 attributes = 0; + public: StmtNodes stmtNodeList; + private: MeStmts meStmtList; BB *group; @@ -586,6 +598,7 @@ class SCCOfBBs { BB *GetEntry() { return entry; } + private: uint32 id; BB *entry; diff --git a/src/mapleall/maple_me/include/hdse.h b/src/mapleall/maple_me/include/hdse.h index c5a637c314..a00188d9c5 100644 --- a/src/mapleall/maple_me/include/hdse.h +++ b/src/mapleall/maple_me/include/hdse.h @@ -14,17 +14,17 @@ */ #ifndef MAPLE_ME_INCLUDE_HDSE_H #define MAPLE_ME_INCLUDE_HDSE_H +#include "alias_class.h" #include "bb.h" -#include "irmap.h" #include "dominance.h" -#include "alias_class.h" +#include "irmap.h" namespace maple { class MeIRMap; class HDSE { public: - HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, - Dominance &pDom, IRMap &map, const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) + HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, Dominance &pDom, IRMap &map, + const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) : hdseDebug(enabledDebug), mirModule(mod), bbVec(bbVec), @@ -48,6 +48,12 @@ class HDSE { void SetRemoveRedefine(bool val) { removeRedefine = val; } + void SetUpdateFreq(bool update) { + updateFreq = update; + } + bool UpdateFreq() { + return updateFreq; + } bool hdseDebug; bool hdseKeepRef = false; @@ -73,10 +79,11 @@ class HDSE { // Or the meExpr is opnd of a same type meExpr static const uint8 kExprTypeNotNull = 2; bool decoupleStatic = false; - bool needUNClean = false; // used to record if there's unreachable BB + bool needUNClean = false; // used to record if there's unreachable BB bool removeRedefine = false; // used to control if run ResolveContinuousRedefine() - MapleVector verstUseCounts; // index is vstIdx - std::forward_list backSubsCands; // backward substitution candidates + bool updateFreq = false; + MapleVector verstUseCounts; // index is vstIdx + std::forward_list backSubsCands; // backward substitution candidates private: void DseInit(); diff --git a/src/mapleall/maple_me/include/me_cfg.h b/src/mapleall/maple_me/include/me_cfg.h index d04e9addb1..8465e37e75 100644 --- a/src/mapleall/maple_me/include/me_cfg.h +++ b/src/mapleall/maple_me/include/me_cfg.h @@ -14,12 +14,13 @@ */ #ifndef MAPLE_ME_INCLUDE_ME_CFG_H #define MAPLE_ME_INCLUDE_ME_CFG_H -#include "me_function.h" #include "maple_phase.h" +#include "me_function.h" namespace maple { class MeCFG : public AnalysisResult { using BBPtrHolder = MapleVector; + public: using value_type = BBPtrHolder::value_type; using size_type = BBPtrHolder::size_type; @@ -86,7 +87,9 @@ class MeCFG : public AnalysisResult { hasDoWhile = hdw; } - MapleAllocator &GetAlloc() { return mecfgAlloc; } + MapleAllocator &GetAlloc() { + return mecfgAlloc; + } void SetNextBBId(uint32 currNextBBId) { nextBBId = currNextBBId; @@ -98,7 +101,9 @@ class MeCFG : public AnalysisResult { --nextBBId; } - MapleVector &GetAllBBs() { return bbVec; } + MapleVector &GetAllBBs() { + return bbVec; + } iterator begin() { return bbVec.begin(); @@ -296,8 +301,19 @@ class MeCFG : public AnalysisResult { void ConstructBBFreqFromStmtFreq(); void ConstructStmtFreq(); void ConstructEdgeFreqFromBBFreq(); - void UpdateEdgeFreqWithNewBBFreq(); - void VerifyBBFreq(); + void UpdateEdgeFreqWithBBFreq(); + int VerifyBBFreq(bool checkFatal = false); + void SetUpdateCFGFreq(bool b) { + updateFreq = b; + } + bool UpdateCFGFreq() const { + return updateFreq; + } + bool DumpIRProfileFile() const { + return dumpIRProfileFile; + } + void ClearFuncFreqInfo(); + private: void AddCatchHandlerForTryBB(BB &bb, MapleVector &exitBlocks); std::string ConstructFileNameToDump(const std::string &prefix) const; @@ -316,11 +332,14 @@ class MeCFG : public AnalysisResult { MapleAllocator mecfgAlloc; MeFunction &func; MapleSet patternSet; - BBPtrHolder bbVec; + BBPtrHolder bbVec; MapleUnorderedMap labelBBIdMap; MapleUnorderedMap bbTryNodeMap; // maps isTry bb to its try stmt MapleUnorderedMap endTryBB2TryBB; // maps endtry bb to its try bb bool hasDoWhile = false; + // following 2 variable are used in profileUse + bool updateFreq = false; // true to maintain cfg frequency in transform phase + bool dumpIRProfileFile = false; // true to dump cfg to files uint32 nextBBId = 0; // BB SCC @@ -331,10 +350,10 @@ class MeCFG : public AnalysisResult { }; MAPLE_FUNC_PHASE_DECLARE_BEGIN(MEMeCfg, MeFunction) - MeCFG *GetResult() { - return theCFG; - } - MeCFG *theCFG = nullptr; +MeCFG *GetResult() { + return theCFG; +} +MeCFG *theCFG = nullptr; MAPLE_MODULE_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(MECfgVerifyFrequency, MeFunction) MAPLE_FUNC_PHASE_DECLARE_END diff --git a/src/mapleall/maple_me/include/me_loop_canon.h b/src/mapleall/maple_me/include/me_loop_canon.h index 248a185127..cd76626574 100644 --- a/src/mapleall/maple_me/include/me_loop_canon.h +++ b/src/mapleall/maple_me/include/me_loop_canon.h @@ -21,7 +21,8 @@ namespace maple { // convert loop to do-while format class MeLoopCanon { public: - MeLoopCanon(MeFunction &f, bool enableDebugFunc) : func(f), isDebugFunc(enableDebugFunc) {} + MeLoopCanon(MeFunction &f, bool enableDebugFunc, bool updateFreq) + : func(f), isDebugFunc(enableDebugFunc), updateFreqs(updateFreq) {} virtual ~MeLoopCanon() = default; void NormalizationExitOfLoop(IdentifyLoops &meLoop); void NormalizationHeadAndPreHeaderOfLoop(Dominance &dom); @@ -33,6 +34,7 @@ class MeLoopCanon { void ResetIsCFGChange() { isCFGChange = false; } + private: void FindHeadBBs(Dominance &dom, const BB *bb, std::map> &heads) const; void SplitPreds(const std::vector &splitList, BB *splittedBB, BB *mergedBB); @@ -44,6 +46,7 @@ class MeLoopCanon { MeFunction &func; bool isDebugFunc; bool isCFGChange = false; + bool updateFreqs = false; }; MAPLE_FUNC_PHASE_DECLARE(MELoopCanon, MeFunction) diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 4b0c81c075..1e5f57be8f 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -14,22 +14,23 @@ */ #ifndef MAPLE_ME_INCLUDE_LOOP_UNROLLING_H #define MAPLE_ME_INCLUDE_LOOP_UNROLLING_H -#include "me_scalar_analysis.h" +#include "me_cfg.h" +#include "me_dominance.h" #include "me_function.h" -#include "me_irmap_build.h" #include "me_ir.h" -#include "me_ssa_update.h" -#include "me_dominance.h" +#include "me_irmap_build.h" #include "me_loop_analysis.h" +#include "me_scalar_analysis.h" +#include "me_ssa_update.h" #include "profile.h" -#include "me_cfg.h" namespace maple { constexpr uint32 kMaxCost = 100; -constexpr uint8 unrollTimes[3] = { 8, 4, 2 }; // unrollTimes +constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll { + enum ReturnKindOfFullyUnroll + { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, @@ -37,14 +38,26 @@ class LoopUnrolling { LoopUnrolling(MeFunction &f, LoopDesc &l, MeIRMap &map, const MapleAllocator &alloc, std::map>> &candsTemp) - : func(&f), cfg(f.GetCfg()), loop(&l), irMap(&map), mpAllocator(alloc), - cands(candsTemp), lastNew2OldBB(mpAllocator.Adapter()), + : func(&f), + cfg(f.GetCfg()), + loop(&l), + irMap(&map), + mpAllocator(alloc), + cands(candsTemp), + lastNew2OldBB(mpAllocator.Adapter()), profValid(func->IsIRProfValid()) {} ~LoopUnrolling() = default; ReturnKindOfFullyUnroll LoopFullyUnroll(int64 tripCount); bool LoopPartialUnrollWithConst(uint64 tripCount); bool LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j); bool LoopUnrollingWithConst(uint64 tripCount, bool onlyFully = false); + void SetInstrumentProf(bool useInstrument) { + instrumentProf = useInstrument; + profValid = useInstrument; + } + bool GetInstrumentProf() const { + return instrumentProf; + } private: bool SplitCondGotoBB(); @@ -53,14 +66,12 @@ class LoopUnrolling { void SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, const BB &exitBB, LabelIdx oldlabIdx); - void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); - void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); + void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); + void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); void UpdateCondGotoBB(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr); void UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, uint32 offset); void CreateIndVarAndCondGotoStmt(CR &cr, CRNode &varNode, BB &preCondGoto, uint32 unrollTime, uint32 i); @@ -85,7 +96,7 @@ class LoopUnrolling { bool canUnroll = true; MeFunction *func; - MeCFG *cfg; + MeCFG *cfg; LoopDesc *loop; MeIRMap *irMap; MapleAllocator mpAllocator; @@ -100,6 +111,7 @@ class LoopUnrolling { bool firstResetForAfterInsertGoto = true; bool resetFreqForUnrollWithVar = false; bool isUnrollWithVar = false; + bool instrumentProf = false; // use instrumented profiling }; class LoopUnrollingExecutor { @@ -109,8 +121,8 @@ class LoopUnrollingExecutor { static bool enableDebug; static bool enableDump; - void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc); + void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc); bool IsCFGChange() const { return isCFGChange; } diff --git a/src/mapleall/maple_me/include/me_profile_use.h b/src/mapleall/maple_me/include/me_profile_use.h index a6a0be8df7..2014e80026 100644 --- a/src/mapleall/maple_me/include/me_profile_use.h +++ b/src/mapleall/maple_me/include/me_profile_use.h @@ -137,8 +137,7 @@ class MeProfUse : public PGOInstrument { bool IsSuccUseProf() const { return succCalcuAllEdgeFreq; } - bool GcovRun(); - GcovFuncInfo *GetFuncData(); + bool MapleProfRun(); bool CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, const std::string &tag); private: bool IsAllZero(Profile::BBInfo &result) const; @@ -147,6 +146,8 @@ class MeProfUse : public PGOInstrument { void ComputeEdgeFreq(); void InitBBEdgeInfo(); void ComputeBBFreq(BBUseInfo &bbInfo, bool &changed); + FuncProfInfo *GetFuncData(); + uint64 SumEdgesCount(const MapleVector &edges) const; BBUseInfo *GetBBUseInfo(const BB &bb) const; BBUseInfo *GetOrCreateBBUseInfo(const BB &bb) ; diff --git a/src/mapleall/maple_me/include/pme_emit.h b/src/mapleall/maple_me/include/pme_emit.h index 85cb7996ec..e9a4628409 100644 --- a/src/mapleall/maple_me/include/pme_emit.h +++ b/src/mapleall/maple_me/include/pme_emit.h @@ -79,7 +79,7 @@ class PreMeEmitter : public AnalysisResult { MapleAllocator* GetCodeMPAlloc() { return codeMPAlloc; } MapleMap *GetPreMeStmtExtensionMap() { return &preMeStmtExtensionMap; } MapleMap *GetPreMeExprExtensionMap() { return &preMeExprExtensionMap; } - GcovFuncInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } + FuncProfInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } private: ArrayNode *ConvertToArray(BaseNode *x, TyIdx ptrTyIdx); diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 7e7e7e5490..290a3c6caa 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,10 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" + +#include + +#include "me_ir.h" +#include "me_ssa.h" #include "mempool_allocator.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "me_ir.h" namespace maple { std::string BB::StrAttribute() const { @@ -80,8 +83,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse) { - mod->GetOut() << " freq: " << frequency << " "; + if (Options::profileUse && frequency >= 0) { + mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; mod->GetOut() << "preds: "; @@ -299,8 +302,8 @@ void BB::MoveAllPredToSucc(BB *newSucc, BB *commonEntry) { } 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 + if (IsSuccBB(*firstPred)) { // avoid replacing twice + firstPred->ReplaceSucc(this, newSucc, true); // firstPred will be removed from this->pred } } } @@ -336,8 +339,8 @@ void BB::MoveAllSuccToPred(BB *newPred, BB *commonExit) { } else { while (!GetSucc().empty()) { BB *firstSucc = GetSucc(0); - if (IsPredBB(*firstSucc)) { // avoid replacing twice - firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ + if (IsPredBB(*firstSucc)) { // avoid replacing twice + firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ } } } @@ -476,23 +479,31 @@ void BB::DumpMePhiList(const IRMap *irMap) { } } -// bb frequency is changed in tranform phase -// update its succ frequency by scaled value -void BB::UpdateEdgeFreqs() { +// update edge frequency by scaled value when bb frequency is changed +void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { int len = GetSucc().size(); ASSERT(len == GetSuccFreq().size(), "sanity check"); int64_t succFreqs = 0; for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - // early return if frequency is consistent - if (len == 0 || succFreqs == GetFrequency()) { - return; - } - for (size_t i = 0; i < len; ++i) { + int diff = abs(succFreqs - GetFrequency()); + if (len == 0 || diff <= 1) return; + int64_t scaledSum = 0; + for (int i = 0; i < len; i++) { int64_t sfreq = GetSuccFreq()[i]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); + scaledSum += scalefreq; SetSuccFreq(i, scalefreq); + // update succ frequency with new difference if needed + if (updateBBFreqOfSucc) { + auto *succ = GetSucc(i); + int64_t diff = scalefreq - sfreq; + int64_t succBBnewFreq = succ->GetFrequency() + diff; + if (succBBnewFreq >= 0) { + succ->SetFrequency(succBBnewFreq); + } + } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 4badba2ad5..99748916e6 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -13,20 +13,22 @@ * See the Mulan PSL v2 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 "opcode_info.h" +#include "ssa_mir_nodes.h" #include "utils.h" +#include "ver_symbol.h" namespace maple { using namespace utils; void HDSE::DetermineUseCounts(MeExpr *x) { if (x->GetMeOp() == kMeOpVar) { - VarMeExpr *varmeexpr = static_cast(x); + VarMeExpr *varmeexpr = static_cast(x); verstUseCounts[varmeexpr->GetVstIdx()]++; return; } @@ -42,7 +44,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (dass->GetRHS()->GetMeOp() != kMeOpVar && dass->GetRHS()->GetMeOp() != kMeOpReg) { return; } - ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); + ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); OriginalSt *ost = lhsscalar->GetOst(); if (!ost->IsLocal()) { return; @@ -51,7 +53,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (ty->GetPrimType() == PTY_agg && ty->GetSize() <= 16) { return; } - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (rhsscalar->GetDefBy() != kDefByMustDef) { return; } @@ -247,6 +249,13 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } } bb.SetKind(kBBFallthru); + if (UpdateFreq()) { + int64_t succ0Freq = bb.GetSuccFreq()[0]; + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + } } // A ivar contained in stmt if (stmt2NotNullExpr.find(mestmt) != stmt2NotNullExpr.end()) { @@ -269,8 +278,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // skip fold conditional branch because it may break recorded IfInfo. bool isPme = mirModule.CurFunction()->GetMeFunc()->GetPreMeFunc() != nullptr; - if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch - CondGotoMeStmt *condbr = static_cast(mestmt); + if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch + CondGotoMeStmt *condbr = static_cast(mestmt); + int64_t removedFreq = 0; if (!mirModule.IsJavaModule() && condbr->GetOpnd()->GetMeOp() == kMeOpConst) { CHECK_FATAL(IsPrimitiveInteger(condbr->GetOpnd()->GetPrimType()), "MeHDSE::DseProcess: branch condition must be integer type"); @@ -278,6 +288,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { (condbr->GetOp() == OP_brfalse && !condbr->GetOpnd()->IsZero())) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().back(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -288,6 +301,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // change to unconditional branch BB *succbb = bb.GetSucc().front(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().front(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -297,6 +313,11 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { GotoMeStmt *gotomestmt = irMap.New(condbr->GetOffset()); bb.ReplaceMeStmt(condbr, gotomestmt); } + if (UpdateFreq()) { + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + } } else { DetermineUseCounts(condbr->GetOpnd()); } @@ -305,17 +326,17 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { DetermineUseCounts(mestmt->GetOpnd(i)); } if (mestmt->GetOp() == OP_dassign) { - CheckBackSubsCandidacy(static_cast(mestmt)); + CheckBackSubsCandidacy(static_cast(mestmt)); } } } mestmt = nextstmt; } // update verstUseCOunts for uses in phi operands - for (std::pair phipair : bb.GetMePhiList()) { + for (std::pair phipair : bb.GetMePhiList()) { if (phipair.second->GetIsLive()) { for (ScalarMeExpr *phiOpnd : phipair.second->GetOpnds()) { - VarMeExpr *varx = dynamic_cast(phiOpnd); + VarMeExpr *varx = dynamic_cast(phiOpnd); if (varx) { verstUseCounts[varx->GetVstIdx()]++; } @@ -334,7 +355,7 @@ bool HDSE::NeedNotNullCheck(MeExpr &meExpr, const BB &bb) { if (meExpr.GetOp() == OP_addrof) { return false; } - if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { + if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { return false; } @@ -446,8 +467,7 @@ void HDSE::MarkRegDefByStmt(RegMeExpr ®MeExpr) { MarkPhiRequired(regMeExpr.GetDefPhi()); break; case kDefByChi: { - ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, - "MarkRegDefByStmt: preg cannot be defined by chi"); + ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, "MarkRegDefByStmt: preg cannot be defined by chi"); auto &defChi = regMeExpr.GetDefChi(); MarkChiNodeRequired(defChi); break; @@ -587,8 +607,7 @@ bool HDSE::ExprNonDeletable(const MeExpr &meExpr) const { } case kMeOpVar: { auto &varMeExpr = static_cast(meExpr); - return varMeExpr.IsVolatile() || - (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); + return varMeExpr.IsVolatile() || (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); } case kMeOpIvar: { auto &opIvar = static_cast(meExpr); @@ -618,7 +637,7 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { switch (op) { case OP_dassign: { auto &dasgn = static_cast(meStmt); - VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); + VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); return (varMeExpr != nullptr && varMeExpr->IsVolatile()) || ExprNonDeletable(*dasgn.GetRHS()) || (hdseKeepRef && dasgn.Propagated()) || dasgn.GetWasMayDassign() || (decoupleStatic && varMeExpr != nullptr && varMeExpr->GetOst()->GetMIRSymbol()->IsGlobal()); @@ -632,8 +651,8 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { 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()); + return ivarMeExpr.IsVolatile() || ivarMeExpr.IsFinal() || ExprNonDeletable(*iasgn.GetLHSVal()->GetBase()) || + ExprNonDeletable(*iasgn.GetRHS()); } default: return false; @@ -862,4 +881,4 @@ void HDSE::DoHDSE() { } RemoveNotRequiredStmts(); } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_me/src/me_bb_layout.cpp b/src/mapleall/maple_me/src/me_bb_layout.cpp index 850a013b07..8c5612db86 100644 --- a/src/mapleall/maple_me/src/me_bb_layout.cpp +++ b/src/mapleall/maple_me/src/me_bb_layout.cpp @@ -13,13 +13,14 @@ * See the Mulan PSL v2 for more details. */ #include "me_bb_layout.h" -#include "me_cfg.h" + #include "bb.h" +#include "maple_phase.h" +#include "me_cfg.h" +#include "me_critical_edge.h" #include "me_irmap.h" #include "me_option.h" #include "me_predict.h" -#include "maple_phase.h" -#include "me_critical_edge.h" // This BB layout strategy strictly obeys source ordering when inside try blocks. // This Optimization will reorder the bb layout. it start from the first bb of func. @@ -114,12 +115,10 @@ void BBLayout::BuildChainForLoops() { auto &loops = meLoop->GetMeLoops(); // sort loops from inner most to outer most // need use the same sort rules as prediction? - std::stable_sort(loops.begin(), loops.end(), [](const LoopDesc *loop1, const LoopDesc *loop2) { - return loop1->nestDepth > loop2->nestDepth; - }); + std::stable_sort(loops.begin(), loops.end(), + [](const LoopDesc *loop1, const LoopDesc *loop2) { return loop1->nestDepth > loop2->nestDepth; }); // build chain for loops one by one - auto *context = - layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); + auto *context = layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); for (auto *loop : loops) { BuildChainForLoop(loop, context); } @@ -188,13 +187,13 @@ void BBLayout::DoBuildChain(const BB &header, BBChain &chain, const MapleVector< } bool BBLayout::IsCandidateSucc(const BB &bb, const BB &succ, const MapleVector *context) { - if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) + if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) return false; } - if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains + if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains return false; } - if (succ.GetBBId() == 1) { // special case, exclude common exit BB + if (succ.GetBBId() == 1) { // special case, exclude common exit BB return false; } return true; @@ -240,7 +239,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } uint32 currEdgeFreq = static_cast(bb.GetEdgeFreq(i)); // attention: entryBB->succFreq[i] is always 0 - if (bb.GetBBId() == 0) { // special case for common entry BB + if (bb.GetBBId() == 0) { // special case for common entry BB CHECK_FATAL(bb.GetSucc().size() == 1, "common entry BB should not have more than 1 succ"); bestSucc = succ; break; @@ -253,7 +252,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector if (bestSucc != nullptr) { if (debugChainLayout) { LogInfo::MapleLogger() << "Select [range1 succ ]: "; - LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; + LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; } return bestSucc; } @@ -267,12 +266,12 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } bool useBBFreq = false; - if (useBBFreq) { // use bb freq + if (useBBFreq) { // use bb freq if (header->GetFrequency() > bestFreq) { // find max bb freq bestFreq = header->GetFrequency(); bestSucc = header; } - } else { // use edge freq + } else { // use edge freq uint32 subBestFreq = 0; for (auto *pred : header->GetPred()) { uint32 curFreq = static_cast(pred->GetEdgeFreq(header)); @@ -595,8 +594,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { // condgoto's succ layout: [0] fallthru succ, [1] target succ, [2-...] eh succ/wontexit succ // goto's succ layout: [0] target succ, [1-...] eh succ/wontexit succ BB *brTargetBB = bb.GetKind() == kBBCondGoto ? bb.GetSucc(1) : bb.GetSucc(0); - CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), - "target is same as fallthru"); + CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), "target is same as fallthru"); if (brTargetBB->GetAttributes(kBBAttrWontExit)) { return; } @@ -608,8 +606,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { bbVisited[bb.GetBBId().GetIdx()] = true; OptimizeBranchTarget(*brTargetBB); // optimize stmt - BB *newTargetBB = - (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); + BB *newTargetBB = (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); if (newTargetBB == brTargetBB) { return; } @@ -682,7 +679,7 @@ void BBLayout::AddBB(BB &bb) { // If the pred bb is goto bb and the target bb of goto bb is the current bb which is be added to layoutBBs, change the // goto bb to fallthru bb. if (layoutBBs.size() > 1) { - BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. + BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. if (predBB->GetKind() != kBBGoto) { return; } @@ -880,7 +877,6 @@ void BBLayout::RemoveUnreachable(BB &bb) { } } - void BBLayout::UpdateNewBBWithAttrTry(const BB &bb, BB &fallthru) const { auto tryBB = &bb; fallthru.SetAttributes(kBBAttrIsTry); @@ -945,6 +941,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { index--; fallthru.AddPred(*newFallthru, index); newFallthru->SetFrequency(fallthru.GetFrequency()); + if (cfg->UpdateCFGFreq()) { + newFallthru->PushBackSuccFreq(fallthru.GetFrequency()); + } if (enabledDebug) { LogInfo::MapleLogger() << "Created fallthru and goto original fallthru" << '\n'; } @@ -954,7 +953,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { } void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { - if (needDealWithTryBB) { return; } + if (needDealWithTryBB) { + return; + } auto *fallthru = bb.GetSucc().front(); while (fallthru && (fallthru->GetPred().size() == 1) && (BBEmptyAndFallthru(*fallthru) || BBContainsOnlyGoto(*fallthru)) && @@ -964,7 +965,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { bb.ReplaceSucc(fallthru, newFallthru); ASSERT(fallthru->GetPred().empty(), "fallthru should not has other pred"); ChangeToFallthruFromCondGoto(bb); - bb.GetSucc().resize(1); // resize succ to 1 + bb.GetSucc().resize(1); // resize succ to 1 } else if (newFallthru->GetPred().size() == 1) { if (newFallthru->GetBBLabel() != 0) { // reset newFallthru label @@ -982,7 +983,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { } void BBLayout::DumpBBPhyOrder() const { - LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; + LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; for (auto bb : layoutBBs) { LogInfo::MapleLogger() << bb->GetBBId(); if (bb != layoutBBs.back()) { @@ -1059,8 +1060,7 @@ void BBLayout::LayoutWithoutProf() { } ASSERT(!(isTry && GetTryOutstanding()), "cannot emit another try if last try has not been ended"); if (nextBB->GetAttributes(kBBAttrIsTryEnd)) { - ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || - IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), + ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), "cannot emit endtry bb before its corresponding try bb"); } } @@ -1204,8 +1204,8 @@ void BBLayout::BuildEdges() { allEdges.emplace_back(layoutAlloc.GetMemPool()->New(bb, dest, w)); } } - std::stable_sort(allEdges.begin(), allEdges.end(), [](const BBEdge *edge1, const BBEdge *edge2) { - return edge1->GetWeight() > edge2->GetWeight(); }); + std::stable_sort(allEdges.begin(), allEdges.end(), + [](const BBEdge *edge1, const BBEdge *edge2) { return edge1->GetWeight() > edge2->GetWeight(); }); } BB *BBLayout::GetBBFromEdges() { @@ -1214,8 +1214,8 @@ BB *BBLayout::GetBBFromEdges() { BB *srcBB = edge->GetSrcBB(); BB *destBB = edge->GetDestBB(); if (enabledDebug) { - LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " - << srcBB->GetEdgeFreq(destBB) << '\n'; + LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " << srcBB->GetEdgeFreq(destBB) + << '\n'; } if (!laidOut[srcBB->GetBBId()]) { @@ -1252,7 +1252,7 @@ BB *BBLayout::NextBBProf(BB &bb) { return NextBBProf(*succBB); } // max freq intial - uint64 maxFreq = 0; + uint64 maxFreq = 0; size_t idx = 0; bool found = false; for (size_t i = 0; i < bb.GetSucc().size(); ++i) { @@ -1282,11 +1282,14 @@ void BBLayout::RebuildFreq() { auto *hook = phase->GetAnalysisInfoHook(); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MEDominance::id); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MELoopAnalysis::id); - dom = static_cast( - hook->ForceRunAnalysisPhase>(&MEDominance::id, func))->GetResult(); + dom = static_cast(hook->ForceRunAnalysisPhase>(&MEDominance::id, func)) + ->GetResult(); meLoop = static_cast( - hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func))->GetResult(); - MePrediction::RebuildFreq(func, *dom, *meLoop); + hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func)) + ->GetResult(); + if (!cfg->UpdateCFGFreq()) { + MePrediction::RebuildFreq(func, *dom, *meLoop); + } } void BBLayout::LayoutWithProf(bool useChainLayout) { @@ -1346,8 +1349,7 @@ void BBLayout::VerifyBB() { if (bb->GetKind() == kBBCondGoto) { auto *fallthru = bb->GetSucc(0); auto *targetBB = bb->GetSucc(1); - if (fallthru == targetBB || - (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { + if (fallthru == targetBB || (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { LogInfo::MapleLogger() << "WARN: cond BB " << bb->GetBBId() << " has same target"; } } @@ -1375,11 +1377,15 @@ bool MEBBLayout::PhaseRun(maple::MeFunction &f) { bbLayout->RunLayout(); f.SetLaidOutBBs(bbLayout->GetBBs()); - if (DEBUGFUNC_NEWPM(f)) { + if (DEBUGFUNC_NEWPM(f) || Options::profileUse) { // verify CFG : check condBB's succs should be different bbLayout->VerifyBB(); bbLayout->DumpBBPhyOrder(); - cfg->DumpToFile("afterBBLayout", false); + if (cfg->UpdateCFGFreq() && cfg->DumpIRProfileFile()) { + cfg->DumpToFile("after-bblayout", false, true); + } else { + cfg->DumpToFile("afterBBLayout", false); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index ae76692bd4..3b9a752fde 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -13,30 +13,33 @@ * See the Mulan PSL v2 for more details. */ #include "me_cfg.h" -#include + #include +#include #include + #include "bb.h" -#include "ssa_mir_nodes.h" -#include "me_irmap.h" -#include "mir_builder.h" #include "me_critical_edge.h" +#include "me_irmap.h" #include "me_loop_canon.h" +#include "mir_builder.h" #include "mir_lower.h" +#include "ssa_mir_nodes.h" namespace { constexpr int kFuncNameLenLimit = 80; } namespace maple { -#define MATCH_STMT(stmt, kOpCode) do { \ - while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ - (stmt) = (stmt)->GetNext(); \ - } \ - if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ - return false; \ - } \ -} while (0) // END define +#define MATCH_STMT(stmt, kOpCode) \ + do { \ + while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ + (stmt) = (stmt)->GetNext(); \ + } \ + if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ + return false; \ + } \ + } while (0) // END define // determine if need to be replaced by assertnonnull bool MeCFG::IfReplaceWithAssertNonNull(const BB &bb) const { const StmtNode *stmt = bb.GetStmtNodes().begin().d(); @@ -308,7 +311,7 @@ bool MeCFG::FindUse(const StmtNode &stmt, StIdx stIdx) const { return FindExprUse(*iNode.GetRHS(), stIdx); } } - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_eval: case OP_free: case OP_switch: { @@ -511,7 +514,6 @@ void MeCFG::FixMirCFG() { } } - // replace "if() throw NPE()" with assertnonnull void MeCFG::ReplaceWithAssertnonnull() { constexpr char rnnTypeName[] = @@ -681,7 +683,7 @@ void MeCFG::ConvertPhiList2IdentityAssigns(BB &meBB) const { DassignNode *dassign = func.GetMIRModule().GetMIRBuilder()->CreateStmtDassign(*st, 0, dread2); func.GetMeSSATab()->GetStmtsSSAPart().SetSSAPartOf( *dassign, func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartMp()->New( - &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); + &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); auto *theSSAPart = static_cast(func.GetMeSSATab()->GetStmtsSSAPart().SSAPartOf(*dassign)); theSSAPart->SetSSAVar(*((*phiIt).second.GetResult())); @@ -700,15 +702,15 @@ void MeCFG::ConvertMePhiList2IdentityAssigns(BB &meBB) const { CHECK_FATAL(ost, "ost is nullptr!"); if (ost->IsSymbolOst() && ost->GetIndirectLev() == 0) { MePhiNode *varPhi = phiIt->second; - auto *dassign = func.GetIRMap()->NewInPool( - static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); + auto *dassign = + func.GetIRMap()->NewInPool(static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); dassign->SetBB(varPhi->GetDefBB()); dassign->SetIsLive(varPhi->GetIsLive()); meBB.PrependMeStmt(dassign); } else if (ost->IsPregOst()) { MePhiNode *regPhi = phiIt->second; - auto *regAss = func.GetIRMap()->New( - OP_regassign, static_cast(regPhi->GetLHS()), regPhi->GetOpnd(0)); + auto *regAss = func.GetIRMap()->New(OP_regassign, static_cast(regPhi->GetLHS()), + regPhi->GetOpnd(0)); regPhi->GetLHS()->SetDefByStmt(*regAss); regPhi->GetLHS()->SetDefBy(kDefByStmt); regAss->SetBB(regPhi->GetDefBB()); @@ -779,6 +781,10 @@ void MeCFG::WontExitAnalysis() { newBB->SetKindReturn(); newBB->SetAttributes(kBBAttrArtificial); bb->AddSucc(*newBB); + // newBB is added as succ of bb, set freq 0 as its edge frequency + if (updateFreq) { + bb->PushBackSuccFreq(0); + } GetCommonExitBB()->AddExit(*newBB); bb->FindWillExitBBs(currVisitedBBs); // Mark other bbs in the loop as visited. } @@ -835,15 +841,13 @@ void MeCFG::VerifyLabels() const { if (stmtNodes.back().GetOpCode() == OP_throw) { continue; } - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in goto"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in goto"); } else if (mirBB->GetKind() == kBBCondGoto) { - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in conditional branch"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in conditional branch"); } else if (mirBB->GetKind() == kBBSwitch) { auto &switchStmt = static_cast(stmtNodes.back()); LabelIdx targetLabIdx = switchStmt.GetDefaultLabel(); @@ -966,7 +970,7 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge return; } std::ofstream cfgFile; - std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer + std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer std::streambuf *buf = cfgFile.rdbuf(); LogInfo::MapleLogger().rdbuf(buf); const std::string &fileName = ConstructFileNameToDump(prefix); @@ -980,7 +984,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge if (bIt == common_exit()) { // specical case for common_exit_bb for (auto it = bb->GetPred().begin(); it != bb->GetPred().end(); ++it) { - cfgFile << "BB" << (*it)->GetBBId()<< " -> " << "BB" << bb->GetBBId() << "[style=dotted];\n"; + cfgFile << "BB" << (*it)->GetBBId() << " -> " + << "BB" << bb->GetBBId() << "[style=dotted];\n"; } continue; } @@ -989,7 +994,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } for (auto it = bb->GetSucc().begin(); it != bb->GetSucc().end(); ++it) { - cfgFile << "BB" << bb->GetBBId() << " -> " << "BB" << (*it)->GetBBId(); + cfgFile << "BB" << bb->GetBBId() << " -> " + << "BB" << (*it)->GetBBId(); if (bb == GetCommonEntryBB()) { cfgFile << "[style=dotted]"; continue; @@ -1013,20 +1019,19 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } } if (laidOut != nullptr) { - static std::vector colors = { - "indianred1", "darkorange1", "lightyellow1", "green3", "cyan", "dodgerblue2", "purple2" - }; + static std::vector colors = {"indianred1", "darkorange1", "lightyellow1", "green3", + "cyan", "dodgerblue2", "purple2"}; uint32 colorIdx = 0; size_t clusterSize = laidOut->size() / colors.size(); uint32 cnt = 0; for (uint32 i = 0; i < laidOut->size(); ++i) { auto *bb = (*laidOut)[i]; auto bbId = bb->GetBBId(); - std::string bbNameLabel = dumpEdgeFreq ? - "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) : - "BB" + std::to_string(bbId.GetIdx()); - cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] << ", label=" << - bbNameLabel << "__" << i << "]\n"; + std::string bbNameLabel = + dumpEdgeFreq ? "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) + : "BB" + std::to_string(bbId.GetIdx()); + cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] + << ", label=" << bbNameLabel << "__" << i << "]\n"; ++cnt; if (cnt > clusterSize) { cnt = 0; @@ -1147,8 +1152,8 @@ bool MeCFG::UnifyRetBBs() { if (func.GetMirFunc()->IsReturnVoid()) { newRetBB->SetFirst(mirBuilder->CreateStmtReturn(nullptr)); } else { - unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", - kStVar, kScAuto, func.GetMirFunc(), kScopeLocal); + unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", kStVar, kScAuto, + func.GetMirFunc(), kScopeLocal); newRetBB->SetFirst(mirBuilder->CreateStmtReturn(mirBuilder->CreateExprDread(*unifiedFuncRet))); } newRetBB->SetLast(newRetBB->GetStmtNodes().begin().d()); @@ -1364,8 +1369,8 @@ void MeCFG::CreateBasicBlocks() { } break; } - // fall thru to handle as return - [[clang::fallthrough]]; + // fall thru to handle as return + [[clang::fallthrough]]; case OP_gosub: case OP_retsub: case OP_return: { @@ -1397,7 +1402,7 @@ void MeCFG::CreateBasicBlocks() { if (!curBB->IsEmpty()) { StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1430,7 +1435,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1461,7 +1466,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1592,7 +1597,7 @@ void MeCFG::CreateBasicBlocks() { } } } while (nextStmt != nullptr); - ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping + ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping ASSERT(lastTryBB == nullptr, "unclosed tryBB"); // tryandendtry should be one-one mapping auto *lastBB = curBB; if (lastBB->IsEmpty()) { @@ -1622,8 +1627,7 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { if (succ == nullptr) { continue; } - if (inQueue.find(succ) != inQueue.end() || - std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { + if (inQueue.find(succ) != inQueue.end() || std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { continue; } bool predAllVisited = true; @@ -1651,8 +1655,8 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { } void MeCFG::BuildSCCDFS(BB &bb, uint32 &visitIndex, std::vector &sccNodes, - std::vector &visitedOrder, std::vector &lowestOrder, - std::vector &inStack, std::stack &visitStack) { + std::vector &visitedOrder, std::vector &lowestOrder, std::vector &inStack, + std::stack &visitStack) { uint32 id = bb.UintID(); visitedOrder[id] = visitIndex; lowestOrder[id] = visitIndex; @@ -1780,7 +1784,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M } } else if (currBB.GetKind() == kBBCondGoto) { if (currBB.GetSucc(0) == &newTarget) { - return; // no need to update offset for fallthru BB + return; // no need to update offset for fallthru BB } BB *gotoBB = currBB.GetSucc().at(1); ASSERT(gotoBB == &newTarget, "[FUNC: %s]newTarget is not one of CondGoto's succ BB", func.GetName().c_str()); @@ -1818,7 +1822,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M switchStmt.SetDefaultLabel(label); } for (size_t i = 0; i < switchStmt.GetSwitchTable().size(); ++i) { - LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; + LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; if (caseLabel == oldLabelIdx) { switchStmt.UpdateCaseLabelAt(i, label); } @@ -1875,7 +1879,7 @@ void MeCFG::ConstructEdgeFreqFromBBFreq() { // set bb frequency from stmt record void MeCFG::ConstructBBFreqFromStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1885,13 +1889,14 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { auto eIt = valid_end(); for (auto bIt = valid_begin(); bIt != eIt; ++bIt) { if ((*bIt)->IsEmpty()) continue; - StmtNode& first = (*bIt)->GetFirst(); + StmtNode &first = (*bIt)->GetFirst(); if (funcData->stmtFreqs.count(first.GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[first.GetStmtID()]); } else if (funcData->stmtFreqs.count((*bIt)->GetLast().GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[(*bIt)->GetLast().GetStmtID()]); } else { - LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" << "\n"; + LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" + << "\n"; ASSERT(0, "no freq set"); } } @@ -1912,10 +1917,13 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { ConstructEdgeFreqFromBBFreq(); // clear stmtFreqs since cfg frequency is create funcData->stmtFreqs.clear(); + + // set updateFrequency with true + updateFreq = true; } void MeCFG::ConstructStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1925,14 +1933,13 @@ void MeCFG::ConstructStmtFreq() { for (auto bIt = valid_begin(); bIt != eIt; ++bIt) { auto *bb = *bIt; if (bIt == common_entry()) { - funcData->entry_freq = bb->GetFrequency(); - funcData->real_entryfreq = funcData->entry_freq; + funcData->entryFreq = bb->GetFrequency(); + funcData->realEntryfreq = funcData->entryFreq; } for (auto &stmt : bb->GetStmtNodes()) { Opcode op = stmt.GetOpCode(); // record bb start/end stmt - if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || - stmt.GetStmtID() == bb->GetLast().GetStmtID() || + if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || stmt.GetStmtID() == bb->GetLast().GetStmtID() || IsCallAssigned(op) || op == OP_call) { funcData->stmtFreqs[stmt.GetStmtID()] = bb->GetFrequency(); } @@ -1942,39 +1949,105 @@ void MeCFG::ConstructStmtFreq() { // bb frequency may be changed in transform phase, // update edgeFreq with new BB frequency by scale -void MeCFG::UpdateEdgeFreqWithNewBBFreq() { - for (size_t idx = 0; idx < bbVec.size(); ++idx) { - BB *currBB = bbVec[idx]; - if (currBB == nullptr || currBB->GetSucc().empty()) { +void MeCFG::UpdateEdgeFreqWithBBFreq() { + BuildSCC(); + for (size_t i = 0; i < GetSccTopologicalVec().size(); ++i) { + SCCOfBBs *scc = GetSccTopologicalVec()[i]; + CHECK_FATAL(scc != nullptr, "scc must not be null"); + if (scc->GetBBs().size() > 1) { + BBTopologicalSort(*scc); + } + const uint32 maxLoopCount = 2; + unsigned loopCount = scc->GetBBs().size() > 1 ? maxLoopCount : 1; + for (unsigned j = 0; j < loopCount; ++j) { + for (BB *bb : scc->GetBBs()) { + if (bb == nullptr) { + continue; + } + // collect pred total except entry + if (!bb->GetAttributes(kBBAttrIsEntry)) { + int64_t inputFreq = 0; + for (auto *pred : bb->GetPred()) { + int idx = pred->GetSuccIndex(*bb); + ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); + inputFreq += pred->GetSuccFreq()[idx]; + } + bb->SetFrequency(inputFreq); + } + // make bb frequency and succs frequency consistent + bb->UpdateEdgeFreqs(false); + } + } + } +} + +void MeCFG::ClearFuncFreqInfo() { + SetUpdateCFGFreq(false); + func.GetMirFunc()->SetFuncProfData(nullptr); + auto &bbVec = GetAllBBs(); + for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit + auto *bb = bbVec[i]; + if (bb == nullptr) { continue; } - // make bb frequency and succs frequency consistent - currBB->UpdateEdgeFreqs(); + bb->SetFrequency(0); + bb->GetSuccFreq().clear(); } } -void MeCFG::VerifyBBFreq() { +// return value is 0 means pass verification, else has problem +int MeCFG::VerifyBBFreq(bool checkFatal) { + int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + ASSERT(entryFreq >= 0, "sanity check"); + bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit auto *bb = bbVec[i]; if (bb == nullptr || bb->GetAttributes(kBBAttrIsEntry) || bb->GetAttributes(kBBAttrIsExit)) { continue; } - // wontexit bb may has wrong succ, skip it + // check case 1: entry count is zero, internal bb has frequency value > 0 + if (entryIsZero && bb->GetFrequency() > 0) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: function entryFreq is zero but internal bb frequency > 0"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } + // check case 2: bb succ frequence numbers should be equal to succ number except wontexit bb + // may has wrong succ, skip it if (bb->GetSuccFreq().size() != bb->GetSucc().size() && !bb->GetAttributes(kBBAttrWontExit)) { - CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + } else { + ClearFuncFreqInfo(); + return 1; + } } - // bb freq == sum(out edge freq) + // check case 3: bb freq == sum(out edge freq) uint64 succSumFreq = 0; for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } if (succSumFreq != bb->GetFrequency()) { - LogInfo::MapleLogger() << "[VerifyFreq failure] BB" << bb->GetBBId() << " freq: " << - bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq << std::endl; - LogInfo::MapleLogger() << func.GetName() << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + int diff = succSumFreq - bb->GetFrequency(); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } } } + return 0; } bool MEMeCfg::PhaseRun(MeFunction &f) { @@ -2008,31 +2081,33 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (!f.GetMIRModule().IsJavaModule() && MeOption::unifyRets) { theCFG->UnifyRetBBs(); } + theCFG->Verify(); // construct bb freq from stmt freq if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { theCFG->ConstructBBFreqFromStmtFreq(); + if (theCFG->DumpIRProfileFile()) { + std::string fileName = "after-mecfgbuild"; + if (f.IsPme()) { + fileName.append("-lfo"); + } else { + fileName.append("-mplme"); + } + theCFG->DumpToFile(fileName, false, true); + } } - theCFG->Verify(); return false; } bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + // if transform pass is not fully support, set disableFreqInfo to true + // function profile information will be deleted after verification phase + bool disableFreqInfo = false; + if (f.GetCfg()->UpdateCFGFreq()) { f.GetCfg()->VerifyBBFreq(); } - // hack code here: no use profile data after verifycation pass since - // following tranform phases related of cfg change are not touched - f.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = f.GetCfg()->GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; - if (bb == nullptr) { - continue; - } - bb->SetFrequency(0); - bb->GetSuccFreq().clear(); - } - + if (!disableFreqInfo) return false; + // clear function profile information + f.GetCfg()->ClearFuncFreqInfo(); return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_critical_edge.cpp b/src/mapleall/maple_me/src/me_critical_edge.cpp index e47078d693..4dca8f82a2 100644 --- a/src/mapleall/maple_me/src/me_critical_edge.cpp +++ b/src/mapleall/maple_me/src/me_critical_edge.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_critical_edge.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" #include "me_function.h" -#include "me_loop_analysis.h" #include "me_irmap.h" +#include "me_loop_analysis.h" +#include "me_option.h" // This phase finds critical edges and split them into two, because their // presence would restrict the optimizations performed by SSAPRE-based phases. @@ -98,8 +100,8 @@ void MeSplitCEdge::UpdateCaseLabel(BB &newBB, MeFunction &func, BB &pred, BB &su } } -void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, - BB &succ, BB *&newBB, bool &isInsertAfterPred) const { +void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, BB &succ, BB *&newBB, + bool &isInsertAfterPred) const { if ((!succ.GetStmtNodes().empty() && succ.GetStmtNodes().front().GetOpCode() == OP_try) || (!succ.IsMeStmtEmpty() && succ.GetFirstMe()->GetOp() == OP_try)) { newBB = &func.GetCfg()->InsertNewBasicBlock(pred, false); @@ -117,8 +119,8 @@ void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const { if (isDebugFunc) { - LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << - succ.GetBBId() << "\n"; + LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << succ.GetBBId() + << "\n"; pred.Dump(&func.GetMIRModule()); succ.Dump(&func.GetMIRModule()); } @@ -160,8 +162,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const newBB->SetAttributes(kBBAttrArtificial); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData() && - (!(func.IsPme() || func.IsLfo()))) { + if (cfg->UpdateCFGFreq() && (!(func.IsPme() || func.IsLfo()))) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -189,8 +190,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const } // profileGen invokes MESplitCEdge to remove critical edges without going through ME completely // newBB needs to be materialized - if (Options::profileGen || - (Options::profileUse && (func.IsPme() || func.IsLfo()))) { + if (Options::profileGen || (Options::profileUse && (func.IsPme() || func.IsLfo()))) { LabelIdx succLabel = succ.GetBBLabel(); ASSERT(succLabel != 0, "succ's label missed"); if (func.GetIRMap() != nullptr) { @@ -306,7 +306,7 @@ bool MESplitCEdge::PhaseRun(maple::MeFunction &f) { mscedge.SplitCriticalEdgeForMeFunc(f); if (Options::profileUse) { if ((f.IsPme() || f.IsLfo()) && f.GetPreMeFunc()) { - // new inserted BB will break while/if label information and IR layout + // new inserted BB break cached while/if label information and IR layout f.GetPreMeFunc()->label2IfInfo.clear(); f.GetPreMeFunc()->label2WhileInfo.clear(); f.GetPreMeFunc()->pmeCreatedIfLabelSet.clear(); diff --git a/src/mapleall/maple_me/src/me_dse.cpp b/src/mapleall/maple_me/src/me_dse.cpp index c2ad027a7e..2d393a9ada 100644 --- a/src/mapleall/maple_me/src/me_dse.cpp +++ b/src/mapleall/maple_me/src/me_dse.cpp @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "me_dse.h" + #include namespace maple { @@ -33,7 +34,7 @@ void MeDSE::VerifyPhi() const { const OriginalSt *ost = func.GetMeSSATab()->GetOriginalStFromID(pair.first); CHECK_FATAL(ost, "ost is nullptr!"); CHECK_FATAL(!ost->IsSymbolOst() || ost->GetIndirectLev() != 0, - "phi is live and non-virtual in bb with zero or one pred"); + "phi is live and non-virtual in bb with zero or one pred"); } else if (pair.second.GetPhiOpnds().size() != predBBNums) { ASSERT(false, "phi opnd num is not consistent with pred bb num(need update phi)"); } @@ -71,8 +72,11 @@ bool MEDse::PhaseRun(maple::MeFunction &f) { f.Verify(); // cfg change , invalid results in MeFuncResultMgr if (dse.UpdatedCfg()) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { - f.GetCfg()->UpdateEdgeFreqWithNewBBFreq(); + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile(("after-dse" + std::to_string(f.dseRuns)), false, true); + } } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); } diff --git a/src/mapleall/maple_me/src/me_emit.cpp b/src/mapleall/maple_me/src/me_emit.cpp index 5cb2c2a710..eaea1c8ede 100644 --- a/src/mapleall/maple_me/src/me_emit.cpp +++ b/src/mapleall/maple_me/src/me_emit.cpp @@ -81,7 +81,7 @@ bool MEEmit::PhaseRun(maple::MeFunction &f) { mirFunction->SetBody(mirFunction->GetCodeMempool()->New()); if (Options::profileUse && mirFunction->GetFuncProfData()) { mirFunction->GetFuncProfData()->SetStmtFreq(mirFunction->GetBody()->GetStmtID(), - mirFunction->GetFuncProfData()->entry_freq); + mirFunction->GetFuncProfData()->entryFreq); } // initialize is_deleted field to true; will reset when emitting Maple IR for (size_t k = 1; k < mirFunction->GetSymTab()->GetSymbolTableSize(); ++k) { diff --git a/src/mapleall/maple_me/src/me_hdse.cpp b/src/mapleall/maple_me/src/me_hdse.cpp index 6283697dd9..9cc7fa1907 100644 --- a/src/mapleall/maple_me/src/me_hdse.cpp +++ b/src/mapleall/maple_me/src/me_hdse.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_hdse.h" + #include + +#include "hdse.h" +#include "me_ssa.h" #include "ssa_mir_nodes.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "hdse.h" // The hdse phase performs dead store elimination using the well-known algorithm // based on SSA. The algorithm works as follows: @@ -55,7 +57,7 @@ void MeHDSE::ProcessWhileInfos() { if (preMeFunc == nullptr) { return; } - MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); + MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); for (; it != preMeFunc->label2WhileInfo.end(); ++it) { if (it->second->initExpr != nullptr && (it->second->initExpr->GetMeOp() == maple::kMeOpVar || it->second->initExpr->GetMeOp() == maple::kMeOpReg)) { @@ -66,7 +68,7 @@ void MeHDSE::ProcessWhileInfos() { void MeHDSE::BackwardSubstitution() { for (DassignMeStmt *dass : backSubsCands) { - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (verstUseCounts[rhsscalar->GetVstIdx()] != 1) { continue; } @@ -110,9 +112,8 @@ void MakeEmptyTrysUnreachable(MeFunction &func) { } BB *endTry = *endTryIt; auto &meStmts = tryBB->GetMeStmts(); - if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && - meStmts.front().GetOp() == OP_try && tryBB->GetMePhiList().empty() && - endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { + if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && meStmts.front().GetOp() == OP_try && + tryBB->GetMePhiList().empty() && endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { // we found a try BB followed by an empty endtry BB BB *targetBB = endTry->GetSucc(0); while (!tryBB->GetPred().empty()) { @@ -190,6 +191,7 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MeHDSE hdse = MeHDSE(f, *dom, *hMap, aliasClass, DEBUGFUNC_NEWPM(f)); hdse.hdseKeepRef = MeOption::dseKeepRef; + hdse.SetUpdateFreq(Options::profileUse && f.GetMirFunc()->GetFuncProfData()); if (f.hdseRuns > 2) { hdse.SetRemoveRedefine(true); } @@ -198,6 +200,13 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MakeEmptyTrysUnreachable(f); (void)f.GetCfg()->UnreachCodeAnalysis(true); f.GetCfg()->WontExitAnalysis(); + // update frequency + if (hdse.UpdateFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-HDSE" + std::to_string(f.hdseRuns), false, true); + } + } if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "\n============== HDSE =============" << '\n'; f.Dump(false); diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 951da51ee7..05c4b15f8e 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_canon.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -39,8 +41,7 @@ void MeLoopCanon::FindHeadBBs(Dominance &dom, const BB *bb, std::mapGetBBLabel() != 0) { - const MapleUnorderedSet &addrTakenLabels = - func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); + const MapleUnorderedSet &addrTakenLabels = func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); if (addrTakenLabels.find(bb->GetBBLabel()) != addrTakenLabels.end()) { hasIgoto = true; } @@ -71,8 +72,7 @@ void MeLoopCanon::UpdateTheOffsetOfStmtWhenTargetBBIsChange(BB &curBB, const BB static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); - } else if (lastStmt.GetOp() == OP_goto && - static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { + } else if (lastStmt.GetOp() == OP_goto && static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); } else if (lastStmt.GetOp() == OP_switch) { @@ -96,8 +96,19 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, // quick split auto *pred = splitList[0]; auto index = pred->GetSuccIndex(*splittedBB); + // add frequency to mergedBB + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + uint64_t freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(freq); + mergedBB->PushBackSuccFreq(freq); + } splittedBB->ReplacePred(pred, mergedBB); pred->AddSucc(*mergedBB, static_cast(static_cast(index))); + if (updateFreqs) { + pred->AddSuccFreq(mergedBB->GetFrequency(), static_cast(static_cast(index))); + } if (!pred->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*pred, *splittedBB, *mergedBB); } @@ -112,6 +123,7 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, mergedBB->GetMePhiList().emplace(latchLhs->GetOstIdx(), latchPhi); phiIter.second->GetOpnds().push_back(latchLhs); } + uint64_t freq = 0; for (BB *pred : splitList) { auto pos = splittedBB->GetPredIndex(*pred); for (auto &phiIter : mergedBB->GetMePhiList()) { @@ -119,7 +131,17 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, phiIter.second->GetOpnds().push_back(splittedBB->GetMePhiList().at(phiIter.first)->GetOpnd(pos)); } splittedBB->RemovePhiOpnd(pos); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + } pred->ReplaceSucc(splittedBB, mergedBB); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*mergedBB); + pred->SetSuccFreq(idx, freq); + } if (pred->GetMeStmts().empty()) { continue; } @@ -141,6 +163,9 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, } } splittedBB->AddPred(*mergedBB); + if (updateFreqs) { + mergedBB->PushBackSuccFreq(mergedBB->GetFrequency()); + } isCFGChange = true; } @@ -151,16 +176,14 @@ void MeLoopCanon::Merge(const std::map> &heads) { BB *head = cfg->GetBBFromID(iter->first); // skip case : check latch bb is already added // one pred is preheader bb and the other is latch bb - if ((head->GetPred().size() == 2) && - (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && - (head->GetPred(0)->GetKind() == kBBFallthru) && - (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && + if ((head->GetPred().size() == 2) && (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && + (head->GetPred(0)->GetKind() == kBBFallthru) && (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && (head->GetPred(1)->GetKind() == kBBFallthru)) { continue; } auto *latchBB = cfg->NewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop latchBB->SetKind(kBBFallthru); SplitPreds(iter->second, head, latchBB); } @@ -244,8 +267,17 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { BB *newExitBB = cfg->NewBasicBlock(); newExitBB->SetKind(kBBFallthru); auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + freq = curBB->GetSuccFreq()[idx]; + } curBB->ReplaceSucc(succ, newExitBB); succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(freq); + newExitBB->PushBackSuccFreq(freq); + } if (!curBB->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } @@ -299,7 +331,8 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { auto *dom = GET_ANALYSIS(MEDominance, f); ASSERT(dom != nullptr, "dom is null in MeDoLoopCanon::Run"); MemPool *loopCanonMp = GetPhaseMemPool(); - auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f)); + bool updateFrequency = (Options::profileUse && f.GetMirFunc()->GetFuncProfData()); + auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f), updateFrequency); // 1. Add preheaderBB and normalization headBB for loop. meLoopCanon->NormalizationHeadAndPreHeaderOfLoop(*dom); @@ -316,6 +349,9 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { meLoopCanon->NormalizationExitOfLoop(*meLoop); if (meLoopCanon->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); + if (updateFrequency && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopcanon", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index 23a572736d..d3f9505fed 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_inversion.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -121,8 +123,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is in loopbody, latchBB need convert condgoto and make original target as its fallthru bool swapSuccOfLatch = (swapSuccs.find(std::make_pair(&bb, &pred)) != swapSuccs.end()); if (isDebugFunc) { - LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " - << pred.GetBBId(); + LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " << pred.GetBBId(); if (swapSuccOfLatch) { LogInfo::MapleLogger() << " need swap succs\n"; } else { @@ -132,9 +133,9 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapNewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop // update newBB frequency : copy predBB succFreq as latch frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { + if (func.GetCfg()->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(bb); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -144,7 +145,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapSetKind(bb.GetKind()); // update succFreq - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { - int succFreqSize = bb.GetSuccFreq().size(); - ASSERT(latchBB->GetSucc().size() == succFreqSize, "sanity check"); - // copy bb succFreq as latch frequency - for (int i = 0; i < succFreqSize; i++) { - latchBB->PushBackSuccFreq(bb.GetSuccFreq()[i]); - } - if (bb.GetFrequency() > 0) { - // swap frequency and fixed the frequency value - if (swapSuccOfLatch) { - ASSERT(latchBB->GetKind() == kBBCondGoto, "impossible"); - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[1] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newtgFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBCondGoto) { - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[0] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); // freq to exit BB - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - // update bb succ frequency - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newftFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { - int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; - latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format - bb.SetSuccFreq(0, bb.GetFrequency()); + if (func.GetCfg()->UpdateCFGFreq()) { + if (latchBB->GetKind() == kBBCondGoto) { + BB *succInloop = swapSuccOfLatch ? bb.GetSucc(0) : bb.GetSucc(1); + if ((latchBB->GetFrequency() != 0) && (succInloop->GetFrequency() > 0)) { + // loop is executed + int64_t latchFreq = latchBB->GetFrequency(); + if (swapSuccOfLatch) { + // bb fallthru is in loop, frequency of bb -> exitbb is set 0 + // latchBB fallthru is loop exit + int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { // assume loop body executed only once + bb.SetSuccFreq(0, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(1, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + latchBB->PushBackSuccFreq(0); + } + } else { + // bb->fallthru is loop exit, edge frequency of bb ->exitbb is set 0 + // latchBB fallthru is in loop + int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(1, bb.GetFrequency()); + bb.SetSuccFreq(0, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { + bb.SetSuccFreq(1, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(0, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + } + } } else { - ASSERT(0, "NYI:: unexpected bb type"); + // loop is not executed + if (latchBB->GetFrequency() != 0) { + if (swapSuccOfLatch) { + bb.SetSuccFreq(0, 0); + bb.SetSuccFreq(1, bb.GetFrequency()); + } else { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + } + } + ASSERT(latchBB->GetFrequency() == 0, "sanity check"); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(0); } + } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { + int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; + latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format + bb.SetSuccFreq(0, bb.GetFrequency()); + } else { + ASSERT(0, "NYI:: unexpected bb type"); } } // swap latchBB's succ if needed @@ -332,8 +355,8 @@ void MeLoopInversion::ExecuteLoopInversion(MeFunction &func, Dominance &dom) { } if ((NeedConvert(&func, *succ, *tmpPred, localAlloc, swapSuccs))) { if (isDebugFunc) { - LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() - << " <-- " << tmpPred->GetBBId() << '\n'; + LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() << " <-- " << tmpPred->GetBBId() + << '\n'; } backEdges.push_back(std::make_pair(succ, tmpPred)); } @@ -362,6 +385,9 @@ bool MELoopInversion::PhaseRun(maple::MeFunction &f) { if (meLoopInversion->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopinversion", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_unrolling.cpp b/src/mapleall/maple_me/src/me_loop_unrolling.cpp index e398584e28..98a5429af0 100644 --- a/src/mapleall/maple_me/src/me_loop_unrolling.cpp +++ b/src/mapleall/maple_me/src/me_loop_unrolling.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_unrolling.h" -#include + #include +#include + #include "me_cfg.h" #include "me_option.h" -#include "mir_module.h" -#include "mir_builder.h" #include "me_phase_manager.h" +#include "mir_builder.h" +#include "mir_module.h" namespace maple { bool LoopUnrollingExecutor::enableDebug = false; @@ -36,13 +38,15 @@ bool ProfileCheck(const maple::MeFunction &f) { auto &profile = f.GetMIRModule().GetProfile(); if (!profile.IsValid()) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" << "\n"; + LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" + << "\n"; } return false; } if (!profile.CheckFuncHot(f.GetName())) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "func is not hot" << "\n"; + LogInfo::MapleLogger() << "func is not hot" + << "\n"; } return false; } @@ -69,12 +73,12 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { case OP_brfalse: case OP_brtrue: case OP_maydassign: - CASE_OP_ASSERT_BOUNDARY { - cost += kTwoInsn; - break; - } + CASE_OP_ASSERT_BOUNDARY { + cost += kTwoInsn; + break; + } case OP_iassign: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_membaracquire: { cost += kThreeInsn; break; @@ -99,7 +103,7 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { } default: if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "consider this op :"<< meStmt.GetOp() << "\n"; + LogInfo::MapleLogger() << "consider this op :" << meStmt.GetOp() << "\n"; } canUnroll = false; break; @@ -152,8 +156,8 @@ void LoopUnrolling::SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -174,8 +178,8 @@ void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2New } // When loop unroll times more than two, use this function to update the preds and succs of duplicate loopbodys. -void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -194,23 +198,22 @@ void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2Ne } } -void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, - BB &curCopyBB, bool copyAllLoop) { +void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, BB &curCopyBB, bool copyAllLoop) { if (resetFreqForUnrollWithVar && copyAllLoop) { if (&curBB == &exitBB && &succ == *loop->inloopBB2exitBBs.begin()->second->begin()) { curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : 1); } if ((&curBB == loop->latch && &succ == loop->head) || (&curBB == &exitBB && &succ == loop->latch)) { - curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : - loop->head->GetFrequency() % replicatedLoopNum - 1); + curCopyBB.PushBackSuccFreq( + loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : loop->head->GetFrequency() % replicatedLoopNum - 1); } else { curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) % replicatedLoopNum); } } else { - profValid && resetFreqForAfterInsertGoto ? - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) : - curBB.GetEdgeFreq(&succ) - 1) : - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); + profValid &&resetFreqForAfterInsertGoto + ? curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) + : curBB.GetEdgeFreq(&succ) - 1) + : curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); } } @@ -252,10 +255,9 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_mapSetFrequency(succ->GetFrequency() % replicatedLoopNum); } } else { - resetFreqForAfterInsertGoto ? - newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : - succ->GetFrequency() - 1) : - newBB->SetFrequency(succ->GetFrequency()); + resetFreqForAfterInsertGoto + ? newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : succ->GetFrequency() - 1) + : newBB->SetFrequency(succ->GetFrequency()); } curCopyBB->AddSucc(*newBB); ResetFrequency(*curBB, *succ, exitBB, *curCopyBB, copyAllLoop); @@ -272,8 +274,8 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop) { +void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop) { CreateLableAndInsertLabelBB(newHeadBB, labelBBs); std::queue bbQue; bbQue.push(loop->head); @@ -308,13 +310,13 @@ void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &ol // Update frequency of old BB. void LoopUnrolling::ResetFrequency(BB &bb) { auto freq = bb.GetFrequency() / replicatedLoopNum; - if (freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { freq = 1; } bb.SetFrequency(static_cast(freq + partialCount)); for (size_t i = 0; i < bb.GetSucc().size(); ++i) { auto currFreq = bb.GetEdgeFreq(i) / replicatedLoopNum; - if (currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { currFreq = 1; } bb.SetEdgeFreq(bb.GetSucc(i), currFreq + partialCount); @@ -366,10 +368,10 @@ void LoopUnrolling::AddEdgeForExitBBLastNew2OldBBEmpty(BB &exitBB, std::unordere bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[bb], idx); if (profValid) { - resetFreqForAfterInsertGoto ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + resetFreqForAfterInsertGoto + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); } ResetOldLabel2NewLabel(old2NewBB, *bb, exitBB, newHeadBB); } @@ -383,10 +385,10 @@ void LoopUnrolling::AddEdgeForExitBB(BB &exitBB, std::unordered_map &o bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[lastNew2OldBB[bb]], idx); if (profValid) { - (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); firstResetForAfterInsertGoto = false; } ResetOldLabel2NewLabel2(old2NewBB, *bb, exitBB, newHeadBB); @@ -403,14 +405,14 @@ void LoopUnrolling::CopyAndInsertBB(bool isPartial) { ResetFrequency(*loop->head); ResetFrequency(); } - profValid && resetFreqForAfterInsertGoto ? - (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) : - newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) : - newHeadBB->SetFrequency(loop->head->GetFrequency()); + profValid &&resetFreqForAfterInsertGoto + ? (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) + : newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) + : newHeadBB->SetFrequency(loop->head->GetFrequency()); (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); if (isPartial) { partialSuccHead = newHeadBB; } @@ -654,7 +656,8 @@ bool LoopUnrolling::LoopPartialUnrollWithConst(uint64 tripCount) { uint32 index = 0; if (!DetermineUnrollTimes(index, true)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "CodeSize is too large" << "\n"; + LogInfo::MapleLogger() << "CodeSize is too large" + << "\n"; } return false; } @@ -710,8 +713,8 @@ void LoopUnrolling::CopyLoopForPartialAndPre(BB *&newHead, BB *&newExiting) { (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; resetFreqForUnrollWithVar = true; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); resetFreqForUnrollWithVar = false; for (auto bb : labelBBs) { if (bb->GetKind() == kBBCondGoto) { @@ -742,8 +745,8 @@ VarMeExpr *LoopUnrolling::CreateIndVarOrTripCountWithName(const std::string &nam } // i < tripcount / unrollTime -void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, - MeExpr &unrollTimeExpr, uint32 offset) { +void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, + uint32 offset) { for (auto &stmt : bb.GetMeStmts()) { bb.RemoveMeStmt(&stmt); } @@ -815,8 +818,8 @@ void LoopUnrolling::CopyLoopForPartial(BB &partialCondGoto, BB &exitedBB, BB &ex partialCondGoto.AddSucc(*partialHead); if (profValid) { partialCondGoto.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum); - partialCondGoto.SetFrequency(static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + - partialCondGoto.GetEdgeFreq(1))); + partialCondGoto.SetFrequency( + static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + partialCondGoto.GetEdgeFreq(1))); } CHECK_FATAL(partialCondGoto.GetKind() == kBBCondGoto, "must be partialCondGoto"); CHECK_FATAL(!partialCondGoto.GetMeStmts().empty(), "must not be empty"); @@ -976,17 +979,19 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) uint32 index = 0; if (!DetermineUnrollTimes(index, false)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "codesize is too large" << "\n"; + LogInfo::MapleLogger() << "codesize is too large" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with var" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with var" + << "\n"; } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); } if (!SplitCondGotoBB()) { return false; @@ -1007,8 +1012,8 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); } return true; } @@ -1022,7 +1027,7 @@ void LoopUnrollingExecutor::SetNestedLoop(const IdentifyLoops &meLoop, CHECK_NULL_FATAL(loop->parent); auto it = parentLoop.find(loop->parent); if (it == parentLoop.end()) { - parentLoop[loop->parent] = { loop }; + parentLoop[loop->parent] = {loop}; } else { parentLoop[loop->parent].insert(loop); } @@ -1065,7 +1070,8 @@ bool LoopUnrollingExecutor::PredIsOutOfLoopBB(const MeFunction &func, LoopDesc & return false; } -bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func, LoopDesc &loop, +bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop( + const MeFunction &func, LoopDesc &loop, const std::unordered_map> &parentLoop) const { // Only handle one nested loop. if (parentLoop.find(&loop) != parentLoop.end() && ProfileCheck(func)) { @@ -1083,7 +1089,8 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func CHECK_FATAL(headBB->GetPred().size() == 2, "head must has two preds"); if (!IsDoWhileLoop(func, loop)) { if (enableDebug) { - LogInfo::MapleLogger() << "While-do loop" << "\n"; + LogInfo::MapleLogger() << "While-do loop" + << "\n"; } return false; } @@ -1100,19 +1107,20 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { if (tripCount == kInvalidTripCount) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "tripCount is invalid" << "\n"; + LogInfo::MapleLogger() << "tripCount is invalid" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "start unrolling with const" << "\n"; + LogInfo::MapleLogger() << "start unrolling with const" + << "\n"; LogInfo::MapleLogger() << "tripCount: " << tripCount << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + std::to_string(loop->head->GetBBId())); } // fully unroll ReturnKindOfFullyUnroll returnKind = LoopFullyUnroll(static_cast(tripCount)); @@ -1121,13 +1129,14 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } if (returnKind == LoopUnrolling::kCanFullyUnroll) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "fully unrolling" << "\n"; + LogInfo::MapleLogger() << "fully unrolling" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() + ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + std::to_string(loop->head->GetBBId())); } return true; } @@ -1137,12 +1146,13 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { // partial unroll with const if (LoopPartialUnrollWithConst(tripCount)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with const" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with const" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); } return true; } @@ -1150,7 +1160,8 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc) { + std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc) { if (enableDebug) { LogInfo::MapleLogger() << func.GetName() << "\n"; } @@ -1168,6 +1179,9 @@ void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMa } LoopScalarAnalysisResult sa(irMap, loop); LoopUnrolling loopUnrolling(func, *loop, irMap, alloc, cands); + if (func.GetCfg()->UpdateCFGFreq()) { + loopUnrolling.SetInstrumentProf(true); + } uint64 tripCount = 0; CRNode *conditionCRNode = nullptr; CR *itCR = nullptr; @@ -1236,6 +1250,9 @@ bool MELoopUnrolling::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-meloopunroll", false, true); + } } if (DEBUGFUNC_NEWPM(f)) { f.GetCfg()->DumpToFile("afterloopunrolling", false); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 0a4d1ea0f7..0041c51b0d 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -13,10 +13,12 @@ * See the Mulan PSL v2 for more details. */ #include "me_profile_use.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_function.h" +#include "me_option.h" namespace maple { BBUseInfo *MeProfUse::GetOrCreateBBUseInfo(const BB &bb) { @@ -206,8 +208,8 @@ bool MeProfUse::BuildEdgeCount() { uint64 hash = ComputeFuncHash(); if (hash != result.funcHash) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " - << result.funcHash << " func real hash " << hash << '\n'; + LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " << result.funcHash + << " func real hash " << hash << '\n'; } return false; } @@ -218,8 +220,8 @@ bool MeProfUse::BuildEdgeCount() { } if (instrumentBBs.size() != result.totalCounter) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << result.totalCounter << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << result.totalCounter + << " func real counter " << instrumentBBs.size() << '\n'; } return false; } @@ -294,12 +296,12 @@ bool MeProfUse::Run() { return true; } -GcovFuncInfo *MeProfUse::GetFuncData() { - GcovProfileData *gcovData = func->GetMIRModule().GetGcovProfile(); - if (!gcovData) { +FuncProfInfo *MeProfUse::GetFuncData() { + MplProfileData *profData = func->GetMIRModule().GetMapleProfile(); + if (!profData) { return nullptr; } - GcovFuncInfo *funcData = gcovData->GetFuncProfile(func->GetUniqueID()); + FuncProfInfo *funcData = profData->GetFuncProfile(func->GetUniqueID()); return funcData; } @@ -315,20 +317,20 @@ bool MeProfUse::CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, c return false; } -bool MeProfUse::GcovRun() { - GcovFuncInfo *funcData = GetFuncData(); +bool MeProfUse::MapleProfRun() { + FuncProfInfo *funcData = GetFuncData(); if (!funcData) { return false; } func->GetMirFunc()->SetFuncProfData(funcData); // early return if lineno fail - if (CheckSumFail(ComputeLinenoHash(), funcData->lineno_checksum, "lineno")) { - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + if (CheckSumFail(ComputeLinenoHash(), funcData->linenoChecksum, "lineno")) { + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } FindInstrumentEdges(); // early return if cfgchecksum fail - if (CheckSumFail(ComputeFuncHash(), funcData->cfg_checksum, "func")) { + if (CheckSumFail(ComputeFuncHash(), funcData->cfgChecksum, "func")) { return false; } std::vector instrumentBBs; @@ -336,12 +338,12 @@ bool MeProfUse::GcovRun() { if (dump) { DumpEdgeInfo(); } - if (instrumentBBs.size() != funcData->num_counts) { + if (instrumentBBs.size() != funcData->edgeCounts) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << funcData->num_counts << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << funcData->edgeCounts + << " func real counter " << instrumentBBs.size() << '\n'; } - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } size_t i = 0; @@ -368,16 +370,23 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { MeProfUse profUse(f, *GetPhaseMemPool(), DEBUGFUNC_NEWPM(f)); bool result = true; if (Options::profileUse) { - result = profUse.GcovRun(); - f.GetCfg()->VerifyBBFreq(); + result = profUse.MapleProfRun(); + if (result) { + result = f.GetCfg()->VerifyBBFreq(); + if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; + } + } } else { profUse.Run(); } - if (result) { + if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "******************after profile use dump function******************\n"; profUse.DumpFuncCFGEdgeFreq(); - f.GetCfg()->DumpToFile("afterProfileUse", false, true); + } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-ProfileUse", false, true); } return true; } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index 33e4e5027a..19425f68fc 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -93,6 +93,10 @@ void ValueRangePropagation::Execute() { dealWithPhi = true; DealWithPhi(**bIt); dealWithPhi = false; + if (func.GetCfg()->UpdateCFGFreq()) { + // update edge frequency + (*bIt)->UpdateEdgeFreqs(false); + } for (auto it = (*bIt)->GetMeStmts().begin(); it != (*bIt)->GetMeStmts().end();) { bool deleteStmt = false; if (!onlyPropVR) { @@ -3132,9 +3136,20 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB UpdateProfile(*pred, bb, unreachableBB); } Insert2UnreachableBBs(unreachableBB); + // update frequency before cfg changed + int64_t removedFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + int idx = bb.GetSuccIndex(unreachableBB); + removedFreq = bb.GetSuccFreq()[idx]; + } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetSuccFreq(0, bb.GetFrequency()); + succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + unreachableBB.SetFrequency(0); + } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); if (loop == nullptr) { return; @@ -3505,6 +3520,12 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3517,7 +3538,16 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + int64_t removedFreq = 0; + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + removedFreq = condGotoBB.GetSuccFreq()[0]; + } condGotoBB.RemoveSucc(*succ0); + if (func.GetCfg()->UpdateCFGFreq()) { + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); } @@ -3675,10 +3705,22 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } return true; } if (CodeSizeIsOverflowOrTheOpOfStmtIsNotSupported(bb)) { @@ -3712,8 +3754,21 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( mergeAllFallthruBBs->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); + if (func.GetCfg()->UpdateCFGFreq()) { + mergeAllFallthruBBs->SetFrequency(edgeFreq); + mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } mergeAllFallthruBBs->AddSucc(trueBranch); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); CreateLabelForTargetBB(pred, *mergeAllFallthruBBs); @@ -3778,19 +3833,48 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + // transform may not be consistent with frequency value + updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + exitCopyFallthru->SetFrequency(edgeFreq); + exitCopyFallthru->PushBackSuccFreq(edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + ASSERT(updatedtrueFreq >= 0, "sanity check"); + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } return true; } auto *newBB = CreateNewGotoBBWithoutCondGotoStmt(bb); @@ -3804,9 +3888,21 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( newBB->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + newBB->SetFrequency(edgeFreq); + newBB->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); @@ -5024,6 +5120,13 @@ bool MEValueRangePropagation::PhaseRun(maple::MeFunction &f) { } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); GetAnalysisInfoHook()->ForceRunTransFormPhase(&MELoopCanon::id, f); + // update cfg frequency + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-valuerange" + std::to_string(f.vrpRuns), false, true); + } + } } // Run vrp twice when need check boundary and nullable pointer. if (MeOption::boundaryCheckMode != kNoCheck || MeOption::npeCheckMode != kNoCheck) { diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index 0c89b82851..abbb818c29 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -13,8 +13,9 @@ * See the Mulan PSL v2 for more details. */ #include "optimizeCFG.h" -#include "me_phase_manager.h" + #include "factory.h" +#include "me_phase_manager.h" namespace maple { namespace { @@ -23,27 +24,27 @@ const char *funcName = nullptr; std::string phaseName; #define LOG_BBID(BB) ((BB)->GetBBId().GetIdx()) -#define DEBUG_LOG() if (debug) \ -LogInfo::MapleLogger() << "[" << phaseName << "] " +#define DEBUG_LOG() \ + if (debug) LogInfo::MapleLogger() << "[" << phaseName << "] " // return {trueBB, falseBB} -std::pair GetTrueFalseBrPair(BB *bb) { +std::pair GetTrueFalseBrPair(BB *bb) { if (bb == nullptr) { - return { nullptr, nullptr }; + return {nullptr, nullptr}; } if (bb->GetKind() == kBBCondGoto) { auto *condBr = static_cast(bb->GetLastMe()); CHECK_FATAL(condBr, "condBr is nullptr!"); if (condBr->GetOp() == OP_brtrue) { - return { bb->GetSucc(1), bb->GetSucc(0) }; + return {bb->GetSucc(1), bb->GetSucc(0)}; } else { ASSERT(condBr->GetOp() == OP_brfalse, "only support brtrue/brfalse"); - return { bb->GetSucc(0), bb->GetSucc(1) }; + return {bb->GetSucc(0), bb->GetSucc(1)}; } } else if (bb->GetKind() == kBBGoto) { - return { bb->GetSucc(0), nullptr }; + return {bb->GetSucc(0), nullptr}; } - return { nullptr, nullptr }; + return {nullptr, nullptr}; } // Only one fallthru is allowed for a bb at most , but a bb may have be more than one fallthru pred @@ -82,7 +83,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { if (expr->GetMeOp() == kMeOpConst || expr->GetMeOp() == kMeOpVar) { return; } - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons exprSet.insert(expr); } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -100,7 +101,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { // expr not throw exception bool IsSafeExpr(const MeExpr *expr) { - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons return false; } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -123,8 +124,7 @@ bool IsSafeExpr(const MeExpr *expr) { bool IsSimpleImm(uint64 imm) { return ((imm & (static_cast(0xffff) << 48u)) == imm) || ((imm & (static_cast(0xffff) << 32u)) == imm) || - ((imm & (static_cast(0xffff) << 16u)) == imm) || - ((imm & (static_cast(0xffff))) == imm) || + ((imm & (static_cast(0xffff) << 16u)) == imm) || ((imm & (static_cast(0xffff))) == imm) || (((~imm) & (static_cast(0xffff) << 48u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 32u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 16u)) == ~imm) || @@ -135,12 +135,12 @@ bool IsSimpleImm(uint64 imm) { // if non-simple imm exist, return it, otherwise return 0 int64 GetNonSimpleImm(MeExpr *expr) { if (expr->GetMeOp() == kMeOpConst && IsPrimitiveInteger(expr->GetPrimType())) { - int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); + int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); if (!IsSimpleImm(static_cast(imm))) { return imm; } } - return 0; // 0 is a simple imm + return 0; // 0 is a simple imm } // Check if ftBB has only one regassign stmt, if regassign exists, return it, otherwise return nullptr @@ -150,7 +150,7 @@ AssignMeStmt *GetSingleAssign(BB *bb) { while (stmt != nullptr && stmt->GetOp() == OP_comment) { stmt = stmt->GetNextMeStmt(); } - if (stmt == nullptr) { // empty bb or has only comment stmt + if (stmt == nullptr) { // empty bb or has only comment stmt return nullptr; } if (stmt->GetOp() == OP_regassign || stmt->GetOp() == OP_dassign) { @@ -193,7 +193,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetPred().empty() && bb->GetSucc().empty() && phiNode.GetOpnds().size() == 1) { @@ -207,7 +207,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetBB() != &currBB; } case kMeOpIvar: { - auto &ivar = static_cast(expr); + auto &ivar = static_cast(expr); if (!IsAllOpndsNotDefByCurrBB(*ivar.GetBase(), currBB, infLoopCheck)) { return false; } @@ -249,8 +249,8 @@ bool IsAllOpndsNotDefByCurrBB(const MeStmt &stmt) { MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { if (IsCompareHasReverseOp(cond->GetOp())) { - return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), - *cond->GetOpnd(0), *cond->GetOpnd(1)); + return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), *cond->GetOpnd(0), + *cond->GetOpnd(1)); } return irmap->CreateMeExprUnary(OP_lnot, cond->GetPrimType(), *cond); } @@ -258,8 +258,7 @@ MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { // Is subSet a subset of superSet? template inline bool IsSubset(const std::set &subSet, const std::set &superSet) { - return std::includes(superSet.begin(), superSet.end(), - subSet.begin(), subSet.end()); + return std::includes(superSet.begin(), superSet.end(), subSet.begin(), subSet.end()); } // before : predCond ---> succCond @@ -269,7 +268,7 @@ bool IsSafeToMergeCond(MeExpr *predCond, MeExpr *succCond) { // Make sure succCond is not dependent on predCond // e.g. if (ptr != nullptr) if (*ptr), the second condition depends on the first one if (predCond == succCond) { - return true; // same expr + return true; // same expr } if (!IsSafeExpr(succCond)) { std::set predSet; @@ -316,9 +315,9 @@ std::unique_ptr GetVRForSimpleCmpExpr(const MeExpr &expr) { if (!IsPrimitiveInteger(opndType)) { return nullptr; } - Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 + Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 if (expr.GetOpnd(1)->GetMeOp() == kMeOpConst) { - MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); + MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); if (constVal->GetKind() != kConstInt) { return nullptr; } @@ -380,7 +379,7 @@ BB *GetCommonDest(BB *predBB, BB *succBB) { } if (psucc0 != succBB && psucc1 != succBB) { - return nullptr; // predBB has no branch to succBB + return nullptr; // predBB has no branch to succBB } BB *commonBB = (psucc0 == succBB) ? psucc1 : psucc0; if (commonBB == nullptr) { @@ -517,7 +516,7 @@ bool UnreachBBAnalysis(const maple::MeFunction &f) { } return false; } -} // anonymous namespace +} // anonymous namespace // contains only one valid goto stmt bool HasOnlyMeGotoStmt(BB &bb) { @@ -600,8 +599,8 @@ bool IsMplEmptyBB(BB &bb) { // connectingBB has only one pred and succ, and has no stmt (except a single gotoStmt) in it bool IsConnectingBB(BB &bb) { return (bb.GetPred().size() == 1 && bb.GetSucc().size() == 1) && - (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty - (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty + (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty + (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty } // RealSucc is a non-connecting BB which is not empty (or has just a single gotoStmt). @@ -664,8 +663,8 @@ void EliminateEmptyConnectingBB(const BB *predBB, BB *emptyBB, const BB *stopBB, while (emptyBB != nullptr && emptyBB != stopBB && IsConnectingBB(*emptyBB)) { BB *succ = emptyBB->GetSucc(0); BB *pred = emptyBB->GetPred(0); - DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) - << "(deleted)->BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) << "(deleted)->BB" + << LOG_BBID(succ) << "\n"; if (pred->IsPredBB(*succ)) { pred->RemoveSucc(*emptyBB, true); emptyBB->RemoveSucc(*succ, true); @@ -688,27 +687,33 @@ bool HasFallthruPred(const BB &bb) { class OptimizeBB { public: OptimizeBB(BB *bb, MeFunction &func, std::map>> *candidates) - : currBB(bb), f(func), cfg(func.GetCfg()), irmap(func.GetIRMap()), - irBuilder(func.GetMIRModule().GetMIRBuilder()), isMeIR(irmap != nullptr), cands(candidates) {} + : currBB(bb), + f(func), + cfg(func.GetCfg()), + irmap(func.GetIRMap()), + irBuilder(func.GetMIRModule().GetMIRBuilder()), + isMeIR(irmap != nullptr), + cands(candidates) {} // optimize each currBB until no change occur bool OptBBIteratively(); // initial factory to create corresponding optimizer for currBB according to BBKind. void InitBBOptFactory(); private: - BB *currBB = nullptr; // BB we currently perform optimization on - MeFunction &f; // function we currently perform optimization on - MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB - MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt - MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode + BB *currBB = nullptr; // BB we currently perform optimization on + MeFunction &f; // function we currently perform optimization on + MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB + MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt + MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode bool isMeIR = false; - std::map>> *cands = nullptr; // candidates ost need to be updated ssa - std::map> candsOstInBB; // bb with ost needed to be updated - - bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization - // opportunity for currBB after a/some optimization, we should set it true. - // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat { + std::map>> *cands = nullptr; // candidates ost need to be updated ssa + std::map> candsOstInBB; // bb with ost needed to be updated + + bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization + // opportunity for currBB after a/some optimization, we should set it true. + // Otherwise it will stop after all optimizations finished and continue to nextBB. + enum BBErrStat + { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -792,23 +797,23 @@ class OptimizeBB { repeatOpt = false; } #define CHECK_CURR_BB() \ -if (!CheckCurrBB()) { \ - return false; \ -} + if (!CheckCurrBB()) { \ + return false; \ + } #define ONLY_FOR_MEIR() \ -if (!isMeIR) { \ - return false; \ -} + if (!isMeIR) { \ + return false; \ + } }; -using OptBBFatory = FunctionFactory; +using OptBBFatory = FunctionFactory; bool OptimizeBB::CheckCurrBB() { - if (bbErrStat != kBBNoErr) { // has been checked before + if (bbErrStat != kBBNoErr) { // has been checked before return false; } - if (currBB == nullptr) { + if (currBB == nullptr) { bbErrStat = kBBErrNull; return false; } @@ -832,9 +837,9 @@ bool OptimizeBB::CheckCurrBB() { void OptimizeBB::UpdateBBIdInSSACand(const BBId &oldBBID, const BBId &newBBID) { auto it = candsOstInBB.find(oldBBID); if (it == candsOstInBB.end()) { - return; // no item to update + return; // no item to update } - auto &ostSet = candsOstInBB[newBBID]; // find or create + auto &ostSet = candsOstInBB[newBBID]; // find or create ostSet.insert(it->second.begin(), it->second.end()); candsOstInBB.erase(it); for (auto &cand : *cands) { @@ -854,7 +859,7 @@ void OptimizeBB::UpdateSSACandForBBPhiList(BB *bb, const BB *newBB) { if (!isMeIR || bb == nullptr || bb->GetMePhiList().empty()) { return; } - if (newBB == nullptr) { // if not specified, newBB is bb itself + if (newBB == nullptr) { // if not specified, newBB is bb itself newBB = bb; } std::set &ostSet = candsOstInBB[newBB->GetBBId()]; @@ -942,18 +947,18 @@ bool OptimizeBB::BranchBB2UncondBB(BB &bb) { } } - DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") - << "BB" << LOG_BBID(&bb) << " to unconditional BB\n"; + DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") << "BB" + << LOG_BBID(&bb) << " to unconditional BB\n"; // delete all empty bb between bb and destBB // note : bb and destBB will be connected after empty BB is deleted for (int i = static_cast(bb.GetSucc().size()) - 1; i >= 0; --i) { EliminateEmptyConnectingBB(&bb, bb.GetSucc(static_cast(i)), destBB, *cfg); } - while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 + while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 ASSERT(bb.GetSucc().back() == destBB, "[FUNC: %s]Goto BB%d has different destination", funcName, LOG_BBID(&bb)); bb.RemoveSucc(*bb.GetSucc().back()); } - if (Options::profileUse && !bb.GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { ASSERT(bb.GetSuccFreq().size() == bb.GetSucc().size(), "sanity check"); bb.SetSuccFreq(0, bb.GetFrequency()); } @@ -1011,30 +1016,32 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { CHECK_FATAL(brStmt, "brStmt is nullptr!"); bool isCondTrue = (!condExpr->IsZero()); bool isBrtrue = (brStmt->GetOp() == OP_brtrue); - if (isCondTrue != isBrtrue) { // goto fallthru BB + if (isCondTrue != isBrtrue) { // goto fallthru BB currBB->RemoveLastMeStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB, true); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { MeStmt *gotoStmt = irmap->CreateGotoMeStmt(f.GetOrCreateBBLabel(*gtBB), currBB, &brStmt->GetSrcPosition()); currBB->ReplaceMeStmt(brStmt, gotoStmt); currBB->SetKind(kBBGoto); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB, true); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1050,25 +1057,27 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { if (isCondTrue != isBrTrue) { currBB->RemoveLastStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { StmtNode *gotoStmt = irBuilder->CreateStmtGoto(OP_goto, f.GetOrCreateBBLabel(*gtBB)); currBB->ReplaceStmt(&brStmt, gotoStmt); currBB->SetKind(kBBGoto); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1151,11 +1160,15 @@ bool OptimizeBB::RemoveSuccFromNoReturnBB() { if (phiNode->GetOpnds().size() < 1) { break; } - phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum + phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum } } (void)EliminateRedundantPhiList(retBB); ResetBBRunAgain(); + // add edge Frequency to exitbb + if (cfg->UpdateCFGFreq()) { + currBB->PushBackSuccFreq(0); + } } return true; } @@ -1207,15 +1220,14 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { } } // update succFreqs before update succs - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData() && - !succ->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq() && !succ->GetSuccFreq().empty()) { // copy succFreqs of succ to pred for (int i = 0; i < succ->GetSuccFreq().size(); i++) { pred->PushBackSuccFreq(succ->GetSuccFreq()[i]); } } succ->MoveAllSuccToPred(pred, cfg->GetCommonExitBB()); - pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. + pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. if (!isSuccEmpty) { // only when we move stmt from succ to pred should we set attr and kind here pred->SetAttributes(succ->GetAttributes()); @@ -1239,11 +1251,11 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { // update bbid : tell ssa-updater to update with new BBID UpdateBBIdInSSACand(succ->GetBBId(), pred->GetBBId()); } - DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) - << ", and delete BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) << ", and delete BB" << LOG_BBID(succ) + << "\n"; UpdateSSACandForBBPhiList(succ, pred); DeleteBB(succ); - succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. + succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. return pred; } @@ -1286,13 +1298,13 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE if (trueExpr == falseExpr) { return true; } - ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName) ; - ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName) ; + ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName); + ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName); // try to simplify select expr MeExpr *selExpr = irmap->CreateMeExprSelect(trueExpr->GetPrimType(), *condExpr, *trueExpr, *falseExpr); MeExpr *simplifiedSel = irmap->SimplifyMeExpr(selExpr); if (simplifiedSel != selExpr) { - return true; // can be simplified + return true; // can be simplified } // We can check for every opnd of opndExpr, and calculate their cost according to cg's insn @@ -1317,30 +1329,30 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE return true; } - // Ignoring connecting BB, two cases can be turn into select - // condBB condBB - // / \ / \ +// Ignoring connecting BB, two cases can be turn into select +// condBB condBB +// / \ / \ // ftBB gtBB | gtBB/ftBB - // x<- x<- | x<- - // \ / \ / - // jointBB jointBB +// x<- x<- | x<- +// \ / \ / +// jointBB jointBB bool OptimizeBB::CondBranchToSelect() { CHECK_CURR_BB(); - BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB - BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB + BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB + BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB if (ftBB == gtBB) { (void)BranchBB2UncondBB(*currBB); return true; } // if ftBB or gtBB itself is jointBB, just return itself; otherwise return real succ - BB *ftTargetBB = (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) - : ftBB; - BB *gtTargetBB = (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) - : gtBB; + BB *ftTargetBB = + (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) : ftBB; + BB *gtTargetBB = + (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) : gtBB; if (ftTargetBB != gtTargetBB) { return false; } - BB *jointBB = ftTargetBB; // common succ + BB *jointBB = ftTargetBB; // common succ // Check if ftBB has only one assign stmt, set ftStmt if a assign stmt exist AssignMeStmt *ftStmt = nullptr; if (ftBB != jointBB) { @@ -1365,7 +1377,7 @@ bool OptimizeBB::CondBranchToSelect() { // Here we found a pattern, collect select opnds and result reg ScalarMeExpr *ftLHS = nullptr; MeExpr *ftRHS = nullptr; - std::set chiListCands; // collect chilist if assign stmt has one + std::set chiListCands; // collect chilist if assign stmt has one if (ftStmt != nullptr) { ftLHS = static_cast(ftStmt->GetLHS()); ftRHS = ftStmt->GetRHS(); @@ -1413,9 +1425,9 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because two ost assigned are not the same\n"; return false; } - DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) - << ", BB" << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; - if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety + DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) << ", BB" + << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; + if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety // black list if (!IsSafeExpr(ftRHS) || !IsSafeExpr(gtRHS)) { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because trueExpr or falseExpr is not safe\n"; @@ -1434,7 +1446,7 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Condition To Select : BB" << LOG_BBID(currBB) << "(cond)->[BB" << LOG_BBID(ftBB) << "(ft), BB" << LOG_BBID(gtBB) << "(gt)]->BB" << LOG_BBID(jointBB) << "(joint)\n"; ScalarMeExpr *resLHS = nullptr; - if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. + if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. // use phinode lhs as result auto it = jointBB->GetMePhiList().find(ftLHS->GetOstIdx()); if (it == jointBB->GetMePhiList().end()) { @@ -1448,7 +1460,7 @@ bool OptimizeBB::CondBranchToSelect() { // It is profitable for instruction selection if select opnd is a compare expression // select condExpr, trueExpr, falseExpr => select cmpExpr, trueExpr, falseExpr if (condExpr->IsScalar() && condExpr->GetPrimType() != PTY_u1) { - auto *scalarExpr = static_cast(condExpr); + auto *scalarExpr = static_cast(condExpr); if (scalarExpr->GetDefBy() == kDefByStmt) { MeStmt *defStmt = scalarExpr->GetDefStmt(); MeExpr *rhs = defStmt->GetRHS(); @@ -1473,7 +1485,7 @@ bool OptimizeBB::CondBranchToSelect() { } (void)BranchBB2UncondBB(*currBB); // update phi - if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred + if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred // just remove phinode jointBB->GetMePhiList().erase(resLHS->GetOstIdx()); } else { @@ -1517,11 +1529,11 @@ bool IsExprSameLexicalally(MeExpr *expr1, MeExpr *expr2) { if (const1->GetKind() == kConstInt) { return static_cast(const1)->GetExtValue() == static_cast(const2)->GetExtValue(); } else if (const1->GetKind() == kConstFloatConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } else if (const1->GetKind() == kConstDoubleConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } return false; } @@ -1707,18 +1719,18 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { } MeExpr *predCond = predBr->GetOpnd(0); MeExpr *succCond = succBr->GetOpnd(0); - auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false - auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false + auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false + auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false // Try to infer result of succCond from predCond bool isPredTrueBrSucc = (FindFirstRealSucc(ptfSucc.first) == &succ); BranchResult tfBranch = InferSuccCondBrFromPredCond(predCond, succCond, isPredTrueBrSucc); - if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond + if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond return false; } // if succ's cond can be inferred from pred's cond, pred can skip succ and branches to newTarget directly BB *newTarget = (tfBranch == kBrTrue) ? FindFirstRealSucc(stfSucc.first) : FindFirstRealSucc(stfSucc.second); if (newTarget == nullptr || newTarget == &succ) { - return false; + return false; } DEBUG_LOG() << "Condition in BB" << LOG_BBID(&succ) << " is redundant, since it has been checked in BB" << LOG_BBID(&pred) << ", BB" << LOG_BBID(&pred) << " can branch to BB" << LOG_BBID(newTarget) << "\n"; @@ -1728,7 +1740,7 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { // succ ... // / \ // ftBB gtBB - if (succ.GetPred().size() == 1) { // succ has only one pred + if (succ.GetPred().size() == 1) { // succ has only one pred // if newTarget is succ's gotoBB, and it has fallthru pred, we should add a goto stmt to succ's last // to replace condGoto stmt. Otherwise, newTarget will have two fallthru pred if (newTarget == FindFirstRealSucc(succ.GetSucc(1)) && HasFallthruPred(*newTarget)) { @@ -1746,7 +1758,17 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { DEBUG_LOG() << "SkipRedundantCond : Remove condBr in BB" << LOG_BBID(&succ) << ", turn it to fallthruBB\n"; } BB *rmBB = (FindFirstRealSucc(succ.GetSucc(0)) == newTarget) ? succ.GetSucc(1) : succ.GetSucc(0); + int64_t deletedSuccFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = succ.GetSuccIndex(*rmBB); + deletedSuccFreq = succ.GetSuccFreq()[idx]; + } succ.RemoveSucc(*rmBB, true); + if (cfg->UpdateCFGFreq()) { + succ.SetSuccFreq(0, succ.GetFrequency()); + auto *succofSucc = succ.GetSucc(0); + succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; } else { @@ -1784,18 +1806,19 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { BB *replacedSucc = isPredTrueBrSucc ? ptfSucc.first : ptfSucc.second; EliminateEmptyConnectingBB(&pred, replacedSucc, &succ, *cfg); ASSERT(pred.IsPredBB(succ), "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName); - int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred - pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it + int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred + pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it DEBUG_LOG() << "Replace succ BB" << LOG_BBID(replacedSucc) << " with BB" << LOG_BBID(newBB) << ": BB" - << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" << " => BB" << LOG_BBID(&pred) - << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) << "\n"; + << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" + << " => BB" << LOG_BBID(&pred) << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) + << "\n"; if (pred.GetSucc(1) == newBB) { cfg->UpdateBranchTarget(pred, succ, *newBB, f); } newTarget->AddPred(*newBB); UpdatePhiForMovingPred(predPredIdx, newBB, &succ, newTarget); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + if (cfg->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -1806,6 +1829,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { uint32_t freqOfSucc = succ.GetFrequency(); ASSERT(freqOfSucc >= freq, "sanity check"); succ.SetFrequency(freqOfSucc - freq); + // update edge frequency + BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; + idx = succ.GetSuccIndex(*affectedBB); + ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); + int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + ASSERT(oldedgeFreq >= freq, "sanity check"); + succ.SetSuccFreq(idx, (oldedgeFreq - freq)); } return true; } @@ -1894,7 +1924,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * // create a new version for new phi phiMeNode->SetLHS(irmap->CreateRegOrVarMeExprVersion(ostIdx)); } - UpdateSSACandForBBPhiList(succ); // new philist has been created in succ + UpdateSSACandForBBPhiList(succ); // new philist has been created in succ } else { // succ has other pred besides curr for (auto &phi : succPhiList) { @@ -1924,7 +1954,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * } else { auto *phiMeNode = irmap->NewInPool(); phiMeNode->SetDefBB(succ); - resPair.first->second = phiMeNode; // replace nullptr inserted before + resPair.first->second = phiMeNode; // replace nullptr inserted before auto &phiOpnds = phiMeNode->GetOpnds(); // insert opnd into New phiNode : all phiOpnds (except for pred) are phiNode lhs in curr phiOpnds.insert(phiOpnds.end(), succ->GetPred().size(), phi.second->GetLHS()); @@ -1963,7 +1993,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (!HasOnlyMeGotoStmt(*succ)) { return false; } - BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB + BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB if (newTarget == succ) { // succ goto itself, no need to update goto target to newTarget return false; @@ -1975,8 +2005,8 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { // pred is moved to newTarget if (pred->GetKind() == kBBFallthru) { CHECK_FATAL(succ->GetLastMe(), "LastMe is nullptr!"); - GotoMeStmt *gotoMeStmt = irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, - &succ->GetLastMe()->GetSrcPosition()); + GotoMeStmt *gotoMeStmt = + irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, &succ->GetLastMe()->GetSrcPosition()); pred->AddMeStmtLast(gotoMeStmt); pred->SetKind(kBBGoto); DEBUG_LOG() << "Insert Uncond stmt to fallthru BB" << LOG_BBID(currBB) << ", and goto BB" << LOG_BBID(newTarget) @@ -1984,15 +2014,29 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { } int predIdx = succ->GetPredIndex(*pred); bool needUpdatePhi = false; + int64_t removedFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*succ); + removedFreq = pred->GetSuccFreq()[idx]; + } if (pred->IsPredBB(*newTarget)) { - pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*newTarget); + pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + } } else { - pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later + pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later needUpdatePhi = true; } - - DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) - << ": BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; + if (cfg->UpdateCFGFreq()) { + int64_t succFreq = succ->GetFrequency(); + ASSERT(succFreq >= removedFreq, "sanity check"); + succ->SetFrequency(succFreq - removedFreq); + succ->SetSuccFreq(0, succ->GetFrequency()); + } + DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) + << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; cfg->UpdateBranchTarget(*pred, *succ, *newTarget, f); if (needUpdatePhi) { // remove phiOpnd in succ, and add phiOpnd to newTarget @@ -2034,7 +2078,7 @@ bool OptimizeBB::OptimizeUncondBB() { return false; } // wont exit BB and has an edge to commonExit, if we merge it to pred and delete it, the egde will be cut off - if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit + if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit ASSERT(currBB->GetAttributes(kBBAttrWontExit), "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName, LOG_BBID(currBB)); return false; @@ -2096,11 +2140,11 @@ bool OptimizeBB::OptimizeSwitchBB() { if (swStmt->GetOpnd()->GetMeOp() != kMeOpConst) { return false; } - auto *swConstExpr = static_cast(swStmt->GetOpnd()); + auto *swConstExpr = static_cast(swStmt->GetOpnd()); MIRConst *swConstVal = swConstExpr->GetConstVal(); ASSERT(swConstVal->GetKind() == kConstInt, "[FUNC: %s]switch is only legal for integer val", funcName); int64 val = static_cast(swConstVal)->GetExtValue(); - BB *survivor = currBB->GetSucc(0); // init as default BB + BB *survivor = currBB->GetSucc(0); // init as default BB for (size_t i = 0; i < swStmt->GetSwitchTable().size(); ++i) { int64 caseVal = swStmt->GetSwitchTable().at(i).first; if (caseVal == val) { @@ -2157,8 +2201,8 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { MeExpr *geConst = geExpr->GetOpnd(1); PrimType lePtyp = leConst->GetPrimType(); PrimType gePtyp = geConst->GetPrimType(); - if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || - lePtyp != gePtyp || !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around + if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || lePtyp != gePtyp || + !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around return nullptr; } int64 leVal = static_cast(static_cast(leConst)->GetConstVal())->GetExtValue(); @@ -2174,9 +2218,9 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { (IsPrimitiveUnsigned(lePtyp) && static_cast(leVal) > static_cast(newGeVal))) { // e.g. x < 3 || x > 2 <==> true return irmap->CreateIntConstMeExpr(1, PTY_u1); - } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 - return irmap->CreateMeExprCompare( - OP_ne, PTY_u1, opndPtyp, *sameExpr, *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); + } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 + return irmap->CreateMeExprCompare(OP_ne, PTY_u1, opndPtyp, *sameExpr, + *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); } // (x < val1 || x > val2) <==> ((unsigned)(x - val1) > (val2 - val1)) MeExpr *newLeConst = irmap->CreateIntConstMeExpr(leVal, opndPtyp); @@ -2255,15 +2299,15 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { return false; } if (!IsProfitableToMergeCond(predCond, succCond)) { - DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" - << LOG_BBID(succ) << " is not simple enough and not profitable\n"; + DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" << LOG_BBID(succ) + << " is not simple enough and not profitable\n"; return false; } // Start trying to merge two condition together if possible - auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches - auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches + auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches + auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches Opcode combinedCondOp = OP_undef; - bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) + bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) // all cases are listed as follow: // | case | predBB -> common | succBB -> common | invertSuccCond | or/and | // | ---- | ---------------- | ---------------- | -------------- | ------ | @@ -2275,16 +2319,16 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // pred's false branch to succ, so true branch to common bool isPredTrueToCommon = (FindFirstRealSucc(ptfBrPair.second) == succ); bool isSuccTrueToCommon = (FindFirstRealSucc(stfBrPair.first) == commonBB); - if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 + if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 invertSuccCond = false; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 + } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 invertSuccCond = false; combinedCondOp = OP_land; - } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 + } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 invertSuccCond = true; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 + } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 invertSuccCond = true; combinedCondOp = OP_land; } else { @@ -2311,7 +2355,7 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // remove succ and update cfg BB *exitBB = isSuccTrueToCommon ? stfBrPair.second : stfBrPair.first; pred->ReplaceSucc(succ, exitBB); - exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. + exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. // we should eliminate edge from succ to commonBB BB *toEliminateBB = isSuccTrueToCommon ? stfBrPair.first : stfBrPair.second; EliminateEmptyConnectingBB(succ, toEliminateBB, commonBB /* stop here */, *cfg); @@ -2354,6 +2398,11 @@ bool OptimizeBB::FoldBranchToCommonDest() { bool OptimizeBB::OptBBOnce() { CHECK_CURR_BB(); DEBUG_LOG() << "Try to optimize BB" << LOG_BBID(currBB) << "...\n"; + // bb frequency may be updated, make bb frequency and succs frequency consistent + // skip deadBB + if (cfg->UpdateCFGFreq() && (!currBB->GetPred().empty()) && (currBB->GetUniquePred() != currBB)) { + currBB->UpdateEdgeFreqs(false); + } bool everChanged = false; // eliminate dead BB : // 1.BB has no pred(expect then entry block) @@ -2416,7 +2465,7 @@ class OptimizeFuntionCFG { private: MeFunction &f; - std::map>> *cands = nullptr; // candidates ost need to update ssa + std::map>> *cands = nullptr; // candidates ost need to update ssa bool OptimizeFuncCFGIteratively(); bool OptimizeCFGForBB(BB *currBB); }; @@ -2439,10 +2488,6 @@ bool OptimizeFuntionCFG::OptimizeFuncCFGIteratively() { if (currBB == nullptr) { continue; } - // bb frequency may be updated, make bb frequency and succs frequency consistent - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { - currBB->UpdateEdgeFreqs(); - } changed |= OptimizeCFGForBB(currBB); } everChanged |= changed; @@ -2488,15 +2533,14 @@ bool OptimizeMeFuncCFG(maple::MeFunction &f, std::mapValidBBNum(); // optimization entry - bool change = OptimizeFuntionCFG(f, ssaCand) - .OptimizeOnFunc(); + bool change = OptimizeFuntionCFG(f, ssaCand).OptimizeOnFunc(); if (change) { f.GetCfg()->WontExitAnalysis(); if (debug) { uint32 bbNumAfter = f.GetCfg()->ValidBBNum(); if (bbNumBefore != bbNumAfter) { - DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") - << " from " << bbNumBefore << " to " << bbNumAfter << "\n"; + DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") << " from " << bbNumBefore + << " to " << bbNumAfter << "\n"; } else { DEBUG_LOG() << "BBs' number keep the same as before (num = " << bbNumAfter << ")\n"; } @@ -2517,6 +2561,9 @@ bool MEOptimizeCFGNoSSA::PhaseRun(MeFunction &f) { debug = DEBUGFUNC_NEWPM(f); phaseName = PhaseName(); bool change = OptimizeMeFuncCFG(f, nullptr); + if (change && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFGNOSSA", false, f.GetCfg()->UpdateCFGFreq()); + } return change; } @@ -2542,7 +2589,10 @@ bool MEOptimizeCFG::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFG", false, f.GetCfg()->UpdateCFGFreq()); + } } return change; } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_me/src/pme_emit.cpp b/src/mapleall/maple_me/src/pme_emit.cpp index 03e2a3cc5c..19cc185ebe 100644 --- a/src/mapleall/maple_me/src/pme_emit.cpp +++ b/src/mapleall/maple_me/src/pme_emit.cpp @@ -1097,7 +1097,7 @@ bool MEPreMeEmission::PhaseRun(MeFunction &f) { mirfunction->SetBody(curblk); // restore bb frequency to stmt if (Options::profileUse && emitter->GetFuncProfData()) { - emitter->GetFuncProfData()->SetStmtFreq(curblk->GetStmtID(), emitter->GetFuncProfData()->entry_freq); + emitter->GetFuncProfData()->SetStmtFreq(curblk->GetStmtID(), emitter->GetFuncProfData()->entryFreq); } uint32 i = 0; while (i < f.GetCfg()->GetAllBBs().size()) { diff --git a/src/mapleall/maple_util/BUILD.gn b/src/mapleall/maple_util/BUILD.gn index a7341eae06..09f912369e 100755 --- a/src/mapleall/maple_util/BUILD.gn +++ b/src/mapleall/maple_util/BUILD.gn @@ -27,6 +27,7 @@ src_libmplutil = [ "src/error_code.cpp", "src/thread_env.cpp", "src/mpl_int_val.cpp", + "src/mpl_profdata.cpp" ] src_libcommandline = [ diff --git a/src/mapleall/maple_util/include/gcov_profile.h b/src/mapleall/maple_util/include/gcov_profile.h deleted file mode 100644 index baf50aa973..0000000000 --- a/src/mapleall/maple_util/include/gcov_profile.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. - * - * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. - * You can use this software according to the terms and conditions of the MulanPSL - 2.0. - * You may obtain a copy of MulanPSL - 2.0 at: - * - * https://opensource.org/licenses/MulanPSL-2.0 - * - * 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 MulanPSL - 2.0 for more details. - */ - -#ifndef MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H -#define MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H - -#include "mempool_allocator.h" -#include -#include - -namespace maple { -using gcov_unsigned_t = unsigned; -using gcov_type = int64_t; -using gcov_type_unsigned = uint64_t; -using location_t = unsigned; -#define HOTCALLSITEFREQ 100 - -enum UpdateFreqOp { - kKeepOrigFreq = 0, - kUpdateOrigFreq = 0x1, - kUpdateFreqbyScale = 0x2, - kUpdateUnrolledFreq = 0x4, - kUpdateUnrollRemainderFreq = 0x8, -}; - -class GcovFuncInfo { - public: - GcovFuncInfo(MapleAllocator* alloc, unsigned funcIdent, unsigned lineno_cs, unsigned cfg_cs) : - ident(funcIdent), lineno_checksum(lineno_cs), cfg_checksum(cfg_cs), counts(alloc->Adapter()) {}; - ~GcovFuncInfo() = default; - - uint64_t GetFuncFrequency() const { return entry_freq; } - void SetFuncFrequency(uint64_t freq) { entry_freq = freq; } - - uint64_t GetFuncRealFrequency() const { return real_entryfreq; } - void SetFuncRealFrequency(uint64_t freq) { real_entryfreq = freq; } - - std::unordered_map& GetStmtFreqs() { - return stmtFreqs; - } - uint64_t GetStmtFreq(uint32_t stmtID) { - if (stmtFreqs.count(stmtID) > 0) { - return stmtFreqs[stmtID]; - } - return -1; // unstored - } - void SetStmtFreq(uint32_t stmtID, uint64_t freq) { - stmtFreqs[stmtID] = freq; - } - void EraseStmtFreq(uint32_t stmtID) { - stmtFreqs.erase(stmtID); - } - void CopyStmtFreq(uint32_t newStmtID, uint32_t origStmtId, bool deleteOld = false) { - ASSERT(GetStmtFreq(origStmtId) >= 0, "origStmtId no freq record"); - SetStmtFreq(newStmtID, GetStmtFreq(origStmtId)); - if (deleteOld) { - EraseStmtFreq(origStmtId); - } - } - bool IsHotCallSite(uint32_t stmtID) { - if (stmtFreqs.count(stmtID) > 0) { - uint64_t freq = stmtFreqs[stmtID]; - return (freq >= HOTCALLSITEFREQ); - } - ASSERT(0, "should not be here"); - return false; - } - unsigned ident; - unsigned lineno_checksum; - unsigned cfg_checksum; - - // Raw arc coverage counts. - unsigned num_counts; - MapleVector counts; - uint64_t entry_freq; // record entry bb frequence - std::unordered_map stmtFreqs; // stmt_id is key, counter value - uint64_t real_entryfreq; // function prof data may be modified after clone/inline -}; - -class GcovProfileData { - public: - GcovProfileData(MapleAllocator *alloc) : funcsCounter(alloc->Adapter()) {} - - GcovFuncInfo *GetFuncProfile(unsigned puidx) { - if (funcsCounter.count(puidx) > 0) { - return funcsCounter[puidx]; - } - return nullptr; - } - void AddFuncProfile(unsigned puidx, GcovFuncInfo *funcData) { - ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); - funcsCounter[puidx] = funcData; - } - MapleUnorderedMap funcsCounter; // use puidx as key -}; - -} // end namespace -#endif // MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H diff --git a/src/mapleall/maple_util/include/mpl_profdata.h b/src/mapleall/maple_util/include/mpl_profdata.h new file mode 100644 index 0000000000..23cf6f99b9 --- /dev/null +++ b/src/mapleall/maple_util/include/mpl_profdata.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#define MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#include +#include +#include "mempool_allocator.h" + +namespace maple { +constexpr uint32_t HOTCALLSITEFREQ = 100; +enum UpdateFreqOp { + kKeepOrigFreq = 0, + kUpdateOrigFreq = 0x1, + kUpdateFreqbyScale = 0x2, + kUpdateUnrolledFreq = 0x4, + kUpdateUnrollRemainderFreq = 0x8, +}; + +// used for record cumulative datas +struct ProfileSummaryHistogram { + uint32_t countRatio; + uint32_t startValue; // count value range in [startValue, nextHistogramStart) + uint32_t countNums; // Number of counters whose profile count falls in countValue range. + uint64_t countMinVal; // Smallest profile count included in this range. + uint64_t countCumValue; // Cumulative value of the profile counts + + ProfileSummaryHistogram(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) + : countRatio(0), startValue(s), countNums(num), countMinVal(mincount), countCumValue(cumcounts) {} +}; + +class ProfileSummary { + public: + explicit ProfileSummary(MapleAllocator *alloc) : histogram(alloc->Adapter()) {} + ProfileSummary(MapleAllocator *alloc, uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, + uint64_t sumcount) + : checkSum(checksum), + run(runtimes), + totalCount(totalcount), + maxCount(maxcount), + sumCount(sumcount), + histogram(alloc->Adapter()) {} + + void SetSummary(uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, uint64_t sumcount) { + checkSum = checksum; + run = runtimes; + totalCount = totalcount; + maxCount = maxcount; + sumCount = sumcount; + } + void AddHistogramRecord(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) { + histogram.push_back(ProfileSummaryHistogram(s, num, mincount, cumcounts)); + } + void DumpSummary(); + uint64_t GetCheckSum() { + return checkSum; + } + uint32_t GetRun() { + return run; + } + uint32_t GetTotalCount() { + return totalCount; + } + uint64_t GetMaxCount() { + return maxCount; + } + uint64_t GetSumCount() { + return sumCount; + } + uint32_t GetHistogramLength() { + return histogram.size(); + } + void ProcessHistogram(); + MapleVector &GetHistogram() { + return histogram; + } + + private: + uint64_t checkSum; // checksum value of module + uint32_t run; // run times + uint32_t totalCount; // number of counters + uint64_t maxCount; // max counter value in single run + uint64_t sumCount; // sum of all counters accumulated. + MapleVector histogram; // record gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; +}; + +class FuncProfInfo { + public: + FuncProfInfo(MapleAllocator *alloc, unsigned funcIdent, unsigned linenoCs, unsigned cfgCs, unsigned countnum = 0) + : ident(funcIdent), + linenoChecksum(linenoCs), + cfgChecksum(cfgCs), + edgeCounts(countnum), + counts(alloc->Adapter()){}; + ~FuncProfInfo() = default; + + uint64_t GetFuncFrequency() const { + return entryFreq; + } + void SetFuncFrequency(uint64_t freq) { + entryFreq = freq; + } + + uint64_t GetFuncRealFrequency() const { + return realEntryfreq; + } + void SetFuncRealFrequency(uint64_t freq) { + realEntryfreq = freq; + } + + std::unordered_map &GetStmtFreqs() { + return stmtFreqs; + } + uint64_t GetStmtFreq(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + return stmtFreqs[stmtID]; + } + return -1; // unstored + } + void SetStmtFreq(uint32_t stmtID, uint64_t freq) { + stmtFreqs[stmtID] = freq; + } + void EraseStmtFreq(uint32_t stmtID) { + stmtFreqs.erase(stmtID); + } + void CopyStmtFreq(uint32_t newStmtID, uint32_t origStmtId, bool deleteOld = false) { + ASSERT(GetStmtFreq(origStmtId) >= 0, "origStmtId no freq record"); + SetStmtFreq(newStmtID, GetStmtFreq(origStmtId)); + if (deleteOld) { + EraseStmtFreq(origStmtId); + } + } + bool IsHotCallSite(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + uint64_t freq = stmtFreqs[stmtID]; + return (freq >= HOTCALLSITEFREQ); + } + ASSERT(0, "should not be here"); + return false; + } + void DumpFunctionProfile(); + + unsigned ident; + unsigned linenoChecksum; + unsigned cfgChecksum; + + // Raw arc coverage counts. + unsigned edgeCounts; + MapleVector counts; + uint64_t entryFreq; // record entry bb frequence + std::unordered_map stmtFreqs; // stmt_id is key, counter value + uint64_t realEntryfreq; // function prof data may be modified after clone/inline +}; + +class MplProfileData { + public: + MplProfileData(MemPool *m, MapleAllocator *a) : funcsCounter(a->Adapter()), summary(a), mp(m), alloc(a) {} + + FuncProfInfo *GetFuncProfile(unsigned puidx) { + if (funcsCounter.count(puidx) > 0) { + return funcsCounter[puidx]; + } + return nullptr; + } + FuncProfInfo *AddNewFuncProfile(unsigned puidx, unsigned linoCs, unsigned cfgCs, unsigned countnum) { + FuncProfInfo *funcProf = mp->New(alloc, puidx, linoCs, cfgCs, countnum); + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcProf; + return funcProf; + } + void AddFuncProfile(unsigned puidx, FuncProfInfo *funcData) { + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcData; + } + void DumpProfileData(); + void DumpFunctionsProfile(); + bool IsHotCallSite(uint64_t freq); + + MapleUnorderedMap funcsCounter; // use puidx as key + // record module profile information and statistics of count information + ProfileSummary summary; + uint64_t hotCountThreshold = 0; + + private: + uint64_t GetHotThreshold(); + + MemPool *mp; + MapleAllocator *alloc; +}; +} // namespace maple +#endif // MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index 250e9ef8ba..c3333b16cf 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -190,6 +190,7 @@ static constexpr const char kBindingProtectedRegionStr[] = "__BindingProtectRegi static constexpr const char kClassNamePrefixStr[] = "L"; static constexpr const char kClassMethodSplitterStr[] = "_3B"; static constexpr const char kFuncGetCurrentCl[] = "MCC_GetCurrentClassLoader"; +static constexpr const char kMplProfFileNameExt[] = ".mprofdata"; // Serve as a global flag to indicate whether frequent strings have been compressed extern bool doCompression; @@ -212,6 +213,10 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); } // namespace namemangler #endif diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp new file mode 100644 index 0000000000..849b262239 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ +#include "mpl_profdata.h" + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { +void ProfileSummary::DumpSummary() { + LogInfo::MapleLogger() << "---------ProfileSummary-------------- \n"; + LogInfo::MapleLogger() << " checkSum: " << std::hex << "0x" << checkSum << "\n"; + LogInfo::MapleLogger() << " runtimes: " << std::dec << run << "\n"; + LogInfo::MapleLogger() << " totalCounts: " << std::dec << totalCount << "\n"; + LogInfo::MapleLogger() << " maxCount: " << std::dec << maxCount << "\n"; + LogInfo::MapleLogger() << " count histogram: countRange countNum minCount cumCount \n"; + for (auto &it : histogram) { + LogInfo::MapleLogger() << " " << std::dec << it.startValue << "\t"; + LogInfo::MapleLogger() << std::dec << it.countNums << "\t" << it.countMinVal << "\t" << it.countCumValue << "\n"; + } +} + +void FuncProfInfo::DumpFunctionProfile() { + LogInfo::MapleLogger() << "function ident " << std::dec << ident; + LogInfo::MapleLogger() << " lino_checksum 0x" << std::hex << linenoChecksum << ", "; + LogInfo::MapleLogger() << " cfg_checksum 0x" << std::hex << cfgChecksum << "\n"; + LogInfo::MapleLogger() << " num_counts " << std::dec << edgeCounts << " : "; + for (unsigned i = 0; i < edgeCounts; i++) { + LogInfo::MapleLogger() << std::dec << " " << counts[i]; + } + LogInfo::MapleLogger() << "\n"; +} + +void MplProfileData::DumpFunctionsProfile() { + LogInfo::MapleLogger() << "---------FunctionProfile-------------- \n"; + for (auto &it : funcsCounter) { + it.second->DumpFunctionProfile(); + } +} + +void MplProfileData::DumpProfileData() { + summary.DumpSummary(); + DumpFunctionsProfile(); +} + +void ProfileSummary::ProcessHistogram() { + int countsum = 0; + int n = histogram.size(); + for (int i = n - 1; i >= 0; i--) { + countsum += histogram[i].countNums; + histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + } +} + +#define HOTRATIO 90 +uint64_t MplProfileData::GetHotThreshold() { + for (auto &it : summary.GetHistogram()) { + if (it.countRatio >= HOTRATIO) { + hotCountThreshold = it.startValue; + } else { + if (hotCountThreshold == 0) { + hotCountThreshold = it.countMinVal; // set minValue in currentRange which satisfy hot ratio + } + return hotCountThreshold; + } + } + // should not be here + return 100; +} + +bool MplProfileData::IsHotCallSite(uint64_t freq) { + auto &h = summary.GetHistogram(); + if (hotCountThreshold == 0) { + if (Options::profileHotCountSeted) { + hotCountThreshold = Options::profileHotCount; + } else if (summary.GetTotalCount() > 0 && !h.empty() && h[0].countRatio == 0) { + // init countRatio and compute hotCountThreshold + summary.ProcessHistogram(); + hotCountThreshold = GetHotThreshold(); + } else if (h.empty()) { + // should not be here + ASSERT(0, "should not be here"); + hotCountThreshold = 1; + } + } + return freq >= hotCountThreshold; +} + +} // namespace maple diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index 8e0411bb22..c333420826 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace namemangler { #ifdef __MRT_DEBUG @@ -585,13 +586,111 @@ size_t GetSleb128Size(int32_t v) { int end = ((v >= 0) ? 0 : -1); while (hasMore) { - // judege whether has More valid rem - hasMore = (rem != end) || - ((static_cast(rem) & 1) != (static_cast((static_cast(v) >> 6)) & 1)); + // judege whether has more valid rem + hasMore = (rem != end) || ((static_cast(rem) & 1) != + (static_cast((static_cast(v) >> 6)) & 1)); size++; v = rem; rem >>= static_cast(kGreybackOffset); // intended signed shift: block codedex here } return size; } + +// encode signed to output stream +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { + bool more; + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + value >>= kGreybackOffset; + more = !((((value == 0) && ((byte & 0x40) == 0)) || + ((value == -1) && ((byte & 0x40) != 0)))); + count++; + if (more) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << static_cast(byte); + } while (more); + return count; +} + +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + value >>= kGreybackOffset; + count++; + if (value != 0) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << char(byte); + } while (value != 0); + return count; +} + +// decode a ULEB128 value. +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + uint64_t value = 0; + unsigned shift = 0; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + uint64_t slice = *p & 0x7f; + if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value += slice << shift; + shift += kGreybackOffset; + } while (*p++ >= 128); + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + +// decode a SLEB128 value. +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + int64_t value = 0; + unsigned shift = 0; + uint8_t byte; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + byte = *p; + uint64_t slice = byte & 0x7f; + if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || + (shift == 63 && slice != 0 && slice != 0x7f)) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value |= slice << shift; + shift += kGreybackOffset; + ++p; + } while (byte >= 128); + // Sign extend negative numbers if needed. + if (shift < 64 && (byte & 0x40)) { + value |= (-1LL) << shift; + } + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + } // namespace namemangler diff --git a/src/mapleall/mpl2mpl/BUILD.gn b/src/mapleall/mpl2mpl/BUILD.gn index c41431ec49..63ba35bebe 100755 --- a/src/mapleall/mpl2mpl/BUILD.gn +++ b/src/mapleall/mpl2mpl/BUILD.gn @@ -57,7 +57,7 @@ src_libmpl2mpl = [ "src/inline_analyzer.cpp", "src/inline_transformer.cpp", "src/method_replace.cpp", - "src/gcov_parser.cpp", + "src/mpl_profdata_parser.cpp", ] configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] diff --git a/src/mapleall/mpl2mpl/include/gcov_parser.h b/src/mapleall/mpl2mpl/include/gcov_parser.h deleted file mode 100644 index 85dcb3566d..0000000000 --- a/src/mapleall/mpl2mpl/include/gcov_parser.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. - * - * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. - * You can use this software according to the terms and conditions of the MulanPSL - 2.0. - * You may obtain a copy of MulanPSL - 2.0 at: - * - * https://opensource.org/licenses/MulanPSL-2.0 - * - * 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 MulanPSL - 2.0 for more details. - */ - -#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#include "mempool.h" -#include "mempool_allocator.h" -#include "bb.h" -#include "maple_phase_manager.h" -#include "gcov_profile.h" - -namespace maple { -using gcov_position_t = unsigned; -// counter defined in gcov-counter.def -enum { - GCOV_COUNTER_ARCS, - GCOV_COUNTER_V_INTERVAL, - GCOV_COUNTER_V_POW2, - GCOV_COUNTER_V_SINGLE, - GCOV_COUNTER_V_INDIR, - GCOV_COUNTER_AVERAGE, - GCOV_COUNTER_IOR, - GCOV_TIME_PROFILER, - GCOV_COUNTER_ICALL_TOPNV, - GCOV_COUNTERS -}; - -class GcovVar { - public: - GcovVar() { - file = nullptr; - buffer = nullptr; - } - FILE *file = nullptr; - gcov_position_t start = 0; - unsigned offset = 0; - unsigned length = 0; - unsigned overread = 0; - int error = 0; - int mode = 0; - int endian = 0; - size_t alloc = 0; - gcov_unsigned_t* buffer = nullptr; -}; - -class MGcovParser : public AnalysisResult { - public: - MGcovParser(MIRModule &mirmod, MemPool *memPool, bool debug) : AnalysisResult(memPool), m(mirmod), - alloc(memPool), localMP(memPool), gcovData(nullptr), dumpDetail(debug) { - gcovVar = localMP->New(); - } - ~MGcovParser() override { - localMP = nullptr; - gcovData = nullptr; - gcovVar = nullptr; - } - int ReadGcdaFile(); - void DumpFuncInfo(); - GcovProfileData *GetGcovData() { return gcovData; } - - private: - using gcov_bucket_type = struct { - gcov_unsigned_t num_counters; - gcov_type min_value; - gcov_type cum_value; - }; - - struct gcov_ctr_summary { - gcov_unsigned_t num; - gcov_unsigned_t runs; - gcov_type sum_all; - gcov_type run_max; - gcov_type sum_max; - gcov_bucket_type histogram[252]; - }; - struct gcov_summary { - gcov_unsigned_t checksum; - struct gcov_ctr_summary ctrs[GCOV_COUNTER_V_INTERVAL]; - }; - - int GcovReadMagic(gcov_unsigned_t magic, gcov_unsigned_t expected); - int GcovOpenFile(const char *name, int mode); - gcov_unsigned_t from_file(gcov_unsigned_t value); - const gcov_unsigned_t *GcovReadWords(unsigned words); - void GcovSync(gcov_position_t base, gcov_unsigned_t length); - int GcovCloseFile(void); - void GcovAllocate(unsigned length); - gcov_unsigned_t GcovReadUnsigned(void); - gcov_position_t GcovGetPosition(void); - gcov_type GcovReadCounter(void); - void GcovReadSummary(struct gcov_summary *summary); - - MIRModule &m; - MapleAllocator alloc; - MemPool *localMP; - GcovProfileData *gcovData; - GcovVar *gcovVar = nullptr; - bool dumpDetail; -}; - -MAPLE_MODULE_PHASE_DECLARE(M2MGcovParser) - -} // end of namespace maple - -#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/include/inline_transformer.h b/src/mapleall/mpl2mpl/include/inline_transformer.h index 8d95a97381..78137411b9 100644 --- a/src/mapleall/mpl2mpl/include/inline_transformer.h +++ b/src/mapleall/mpl2mpl/include/inline_transformer.h @@ -55,7 +55,9 @@ class InlineTransformer { callee(callee), callStmt(callStmt), dumpDetail(dumpDetail), - cg(cg) {} + cg(cg), + updateFreq(Options::profileUse && caller.GetFuncProfData() && callee.GetFuncProfData()){}; + bool PerformInline(BlockNode &enclosingBlk); static void ReplaceSymbols(BaseNode*, uint32, const std::vector*); static void ConvertPStaticToFStatic(MIRFunction &func); @@ -91,6 +93,7 @@ class InlineTransformer { LabelIdx returnLabelIdx = 0; // The lableidx where the code will jump when the callee returns. StmtNode *labelStmt = nullptr; // The LabelNode we created for the callee, if needed. CallGraph *cg = nullptr; + bool updateFreq = false; }; } // namespace maple #endif // MPL2MPL_INCLUDE_INLINE_TRANSFORMER_H diff --git a/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h new file mode 100644 index 0000000000..1a83fa5c83 --- /dev/null +++ b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#include "bb.h" +#include "maple_phase_manager.h" +#include "mempool.h" +#include "mempool_allocator.h" +#include "mpl_profdata.h" + +namespace maple { +// maple profile data format +// Summary layout +// MagicNumber +// chesum +// run times +// counts number +// count Maxium value +// accumulated count sum +// cout histogram size (count statistic information used for hot function check) +// count lower bound <-- begin of histogram details +// countNum in current range +// minium value in count range +// accumulated count sum +// count range <-- another histogram element +// countNum +// minium value in cout range +// accumulated count sum +// Function profile layout (now only including edge profiling counts) +// function numbers +// function Ident (key number to identify each function(now use mirfunction->puidx) +// function line number checksum +// function cfg checksum +// counts number in function 0 +// count <-- begin of count value +// count +// counts number in function 1 +// count +// ... +// now only unsigned number in profile data, use ULEB128 to encode/decode value for file size + +const uint32_t kMapleProfDataMagicNumber = 0xA0EFEF; + +class ProfDataBinaryImportBase { + public: + ProfDataBinaryImportBase(std::string &filename, std::ifstream &input) : fileName(filename), inputStream(input) {} + template + T ReadNum(); + std::ifstream &GetInputStream() { + return inputStream; + } + std::string &GetProfDataFileName() { + return fileName; + } + void SetPosition(uint8_t *p) { + pos = p; + } + uint8_t *GetPosition() { + return pos; + } + + private: + std::string &fileName; + std::ifstream &inputStream; + uint8_t *pos = nullptr; +}; + +class ProfileSummaryImport : public ProfDataBinaryImportBase { + public: + ProfileSummaryImport(std::string &outputFile, std::ifstream &input) : ProfDataBinaryImportBase(outputFile, input) {} + int ReadSummary(MplProfileData*); + + private: + void ReadMProfMagic(); +}; + +class FunctionProfileImport : public ProfDataBinaryImportBase { + public: + FunctionProfileImport(std::string &inputFile, std::ifstream &input) : ProfDataBinaryImportBase(inputFile, input) {} + int ReadFuncProfile(MplProfileData *profData); +}; + +class MplProfDataParser : public AnalysisResult { + public: + MplProfDataParser(MIRModule &mirmod, MemPool *mp, bool debug) + : AnalysisResult(mp), m(mirmod), alloc(memPool), mempool(mp), dumpDetail(debug) {} + ~MplProfDataParser() = default; + MplProfileData *GetProfData() { + return profData; + } + int ReadMapleProfileData(); + + private: + MIRModule &m; + MapleAllocator alloc; + MemPool *mempool; + MplProfileData *profData = nullptr; + bool dumpDetail = false; +}; + +MAPLE_MODULE_PHASE_DECLARE(MMplProfDataParser) + +} // end of namespace maple + +#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/src/call_graph.cpp b/src/mapleall/mpl2mpl/src/call_graph.cpp index 449da87d5c..6dd6a88cab 100644 --- a/src/mapleall/mpl2mpl/src/call_graph.cpp +++ b/src/mapleall/mpl2mpl/src/call_graph.cpp @@ -14,7 +14,6 @@ */ #include "call_graph.h" - #include "option.h" #include "retype.h" #include "string_utils.h" @@ -190,7 +189,7 @@ bool CGNode::IsCalleeOf(CGNode *func) const { } uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo->stmtFreqs.count(callstmt->GetStmtID()) > 0) { return funcInfo->stmtFreqs[callstmt->GetStmtID()]; } @@ -199,9 +198,9 @@ uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { } uint64_t CGNode::GetFuncFrequency() const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo) { - return funcInfo->GetFuncFrequency(); + return funcInfo->GetFuncRealFrequency(); } ASSERT(0, "should not be here"); return 0; @@ -257,8 +256,8 @@ void CallGraph::DelNode(CGNode &node) { } } -CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, - const KlassHierarchy &kh, const std::string &fn) +CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, const KlassHierarchy &kh, + const std::string &fn) : AnalysisResult(&memPool), mirModule(&m), cgAlloc(&memPool), @@ -524,7 +523,7 @@ void CallGraph::RecordLocalConstValue(const StmtNode *stmt) { CallNode *CallGraph::ReplaceIcallToCall(BlockNode &body, IcallNode *icall, PUIdx newPUIdx) { MapleVector opnds(icall->GetNopnd().begin() + 1, icall->GetNopnd().end(), - CurFunction()->GetCodeMPAllocator().Adapter()); + CurFunction()->GetCodeMPAllocator().Adapter()); CallNode *newCall = nullptr; if (icall->GetOpCode() == OP_icall) { newCall = mirBuilder->CreateStmtCall(newPUIdx, opnds, OP_call); @@ -747,8 +746,8 @@ void CallGraph::HandleICall(BlockNode &body, CGNode &node, StmtNode *stmt, uint3 icallToFix.insert({funcType->GetTypeIndex(), tempSet}); } CHECK_FATAL(CurFunction()->GetPuidx() == node.GetPuIdx(), "Error"); - Callsite callSite = { callInfo, node.GetCallee().at(callInfo) }; - icallToFix.at(funcType->GetTypeIndex())->insert({ node.GetPuIdx(), callSite }); + Callsite callSite = {callInfo, node.GetCallee().at(callInfo)}; + icallToFix.at(funcType->GetTypeIndex())->insert({node.GetPuIdx(), callSite}); } void CallGraph::HandleBody(MIRFunction &func, BlockNode &body, CGNode &node, uint32 loopDepth) { @@ -1235,7 +1234,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { Opcode op = stmt->GetOpCode(); switch (op) { case OP_comment: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_brtrue: case OP_brfalse: case OP_try: @@ -1504,7 +1503,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { } } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_call: case OP_callassigned: { CallNode *callNode = static_cast(stmt); @@ -1559,8 +1558,9 @@ void IPODevirtulize::DevirtualFinal() { if (GlobalTables::GetGsymTable().GetSymbolFromStrIdx(classType->GetStaticFieldsGStrIdx(i)) == nullptr) { continue; } - TyIdx tyIdx = GlobalTables::GetGsymTable().GetSymbolFromStrIdx( - classType->GetStaticFieldsPair(i).first)->GetInferredTyIdx(); + TyIdx tyIdx = GlobalTables::GetGsymTable() + .GetSymbolFromStrIdx(classType->GetStaticFieldsPair(i).first) + ->GetInferredTyIdx(); if (tyIdx != kInitTyIdx && tyIdx != kNoneTyIdx) { CHECK_FATAL(attribute.GetAttr(FLDATTR_final), "Must be final private"); if (debugFlag) { @@ -1744,13 +1744,13 @@ void CallGraph::RemoveFileStaticRootNodes() { std::vector staticRoots; std::copy_if(rootNodes.begin(), rootNodes.end(), std::inserter(staticRoots, staticRoots.begin()), [](const CGNode *root) { - // root means no caller, we should also make sure that root is not be used in addroffunc - auto mirFunc = root->GetMIRFunction(); - return root != nullptr && mirFunc != nullptr && // remove before - // if static functions or inline but not extern modified functions are not used anymore, - // they can be removed safely. - !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); - }); + // root means no caller, we should also make sure that root is not be used in addroffunc + auto mirFunc = root->GetMIRFunction(); + return root != nullptr && mirFunc != nullptr && // remove before + // if static functions or inline but not extern modified functions are not used anymore, + // they can be removed safely. + !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); + }); for (auto *root : staticRoots) { // DFS delete root and its callee that is static and have no caller after root is deleted DelNode(*root); diff --git a/src/mapleall/mpl2mpl/src/gcov_parser.cpp b/src/mapleall/mpl2mpl/src/gcov_parser.cpp deleted file mode 100644 index f0f1373e90..0000000000 --- a/src/mapleall/mpl2mpl/src/gcov_parser.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. - * - * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. - * You can use this software according to the terms and conditions of the MulanPSL - 2.0. - * You may obtain a copy of MulanPSL - 2.0 at: - * - * https://opensource.org/licenses/MulanPSL-2.0 - * - * 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 MulanPSL - 2.0 for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "option.h" -#include "mpl_logging.h" -#include "gcov_parser.h" - -namespace maple { -#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */ -#define GCOV_VERSION ((gcov_unsigned_t)0x4137352a) - -#ifndef ATTRIBUTE_UNUSED -#define ATTRIBUTE_UNUSED __attribute__((unused)) -#endif - -/* Convert a magic or version number to a 4 character string. */ -#define GCOV_UNSIGNED2STRING(ARRAY,VALUE) \ - ((ARRAY)[0] = (char)((VALUE) >> 24), \ - (ARRAY)[1] = (char)((VALUE) >> 16), \ - (ARRAY)[2] = (char)((VALUE) >> 8), \ - (ARRAY)[3] = (char)((VALUE) >> 0)) - -#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000) -#define GCOV_TAG_FUNCTION_LENGTH (3) -#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000) -#define GCOV_TAG_BLOCKS_LENGTH(NUM) (NUM) -#define GCOV_TAG_BLOCKS_NUM(LENGTH) (LENGTH) -#define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000) -#define GCOV_TAG_ARCS_LENGTH(NUM) (1 + (NUM) * 2) -#define GCOV_TAG_ARCS_NUM(LENGTH) (((LENGTH) - 1) / 2) -#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000) -#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) -#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) -#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) -#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ -#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) -#define GCOV_TAG_SUMMARY_LENGTH(NUM) \ - (1 + GCOV_COUNTERS_SUMMABLE * (10 + 3 * 2) + (NUM) * 5) -#define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000) -#define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000) -#define GCOV_TAG_AFDO_WORKING_SET ((gcov_unsigned_t)0xaf000000) - -// Convert a counter index to a tag -#define GCOV_TAG_FOR_COUNTER(COUNT) \ - (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17)) - -// Return the number of set bits in X -static int popcount_hwi (unsigned long long x) { - int i, ret = 0; - size_t bits = sizeof (x) * CHAR_BIT; - for (i = 0; i < bits; i += 1) { - ret += x & 1; - x >>= 1; - } - return ret; -} - -gcov_position_t MGcovParser::GcovGetPosition (void) { - ((void)(0 && (gcovVar->mode > 0))); - return gcovVar->start + gcovVar->offset; -} - -int MGcovParser::GcovOpenFile(const char *name, int mode) { - ((void)(0 && (!gcovVar->file))); - gcovVar->start = 0; - gcovVar->offset = gcovVar->length = 0; - gcovVar->overread = -1u; - gcovVar->error = 0; - gcovVar->endian = 0; - gcovVar->alloc = 0; - if (mode >= 0) { - gcovVar->file = fopen(name, (mode > 0) ? "rb" : "r+b"); - } - if (gcovVar->file) { - mode = 1; - } else if (mode <= 0) { - gcovVar->file = fopen(name, "w+b"); - } - if (!gcovVar->file) return 0; - gcovVar->mode = mode ? mode : 1; - setbuf(gcovVar->file, (char *)0); - return 1; -} - -void MGcovParser::GcovAllocate (unsigned length) { - size_t new_size = gcovVar->alloc; - if (!new_size) { - new_size = (1 << 10); - } - new_size += length; - new_size *= 2; - gcovVar->alloc = new_size; - gcovVar->buffer= ((gcov_unsigned_t *) realloc ((gcovVar->buffer), (new_size << 2))); -} - -int MGcovParser::GcovReadMagic(gcov_unsigned_t magic, gcov_unsigned_t expected) { - if (magic == expected) return 1; - magic = (magic >> 16) | (magic << 16); - magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); - if (magic == expected) { - gcovVar->endian = 1; - return -1; - } - return 0; -} - -void MGcovParser::GcovSync(gcov_position_t base, gcov_unsigned_t length) { - ((void)(0 && (gcovVar->mode > 0))); - base += length; - if (base - gcovVar->start <= gcovVar->length) { - gcovVar->offset = base - gcovVar->start; - } else { - gcovVar->offset = gcovVar->length = 0; - fseek (gcovVar->file, base << 2, 0); - gcovVar->start = ftell (gcovVar->file) >> 2; - } -} - -const gcov_unsigned_t * MGcovParser::GcovReadWords (unsigned words) { - const gcov_unsigned_t *result; - unsigned excess = gcovVar->length - gcovVar->offset; - if (gcovVar->mode <= 0) - return nullptr; - if (excess < words) { - gcovVar->start += gcovVar->offset; - if (excess) { - memmove_s(gcovVar->buffer, excess * 4, gcovVar->buffer + gcovVar->offset, excess * 4); - } - gcovVar->offset = 0; - gcovVar->length = excess; - if (gcovVar->length + words > gcovVar->alloc) { - GcovAllocate(gcovVar->length + words); - } - excess = gcovVar->alloc - gcovVar->length; - excess = fread (gcovVar->buffer + gcovVar->length, 1, excess << 2, gcovVar->file) >> 2; - gcovVar->length += excess; - if (gcovVar->length < words) { - gcovVar->overread += words - gcovVar->length; - gcovVar->length = 0; - return 0; - } - } - result = &gcovVar->buffer[gcovVar->offset]; - gcovVar->offset += words; - return result; -} - -gcov_unsigned_t MGcovParser::from_file(gcov_unsigned_t value) { - if (gcovVar->endian) { - value = (value >> 16) | (value << 16); - value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); - } - return value; -} - -gcov_unsigned_t MGcovParser::GcovReadUnsigned(void) { - gcov_unsigned_t value; - const gcov_unsigned_t *buffer = GcovReadWords(1); - if (!buffer) return 0; - value = from_file(buffer[0]); - return value; -} - -int MGcovParser::GcovCloseFile (void) { - if (gcovVar->file) { - fclose (gcovVar->file); - gcovVar->file = 0; - gcovVar->length = 0; - } - free (gcovVar->buffer); - gcovVar->alloc = 0; - gcovVar->buffer = nullptr; - gcovVar->mode = 0; - return gcovVar->error; -} - -gcov_type MGcovParser::GcovReadCounter (void) { - gcov_type value; - const gcov_unsigned_t *buffer = GcovReadWords(2); - if (!buffer) return 0; - value = from_file (buffer[0]); - if (sizeof (value) > sizeof (gcov_unsigned_t)) { - value |= ((gcov_type) from_file (buffer[1])) << 32; - } else if (buffer[1]) { - gcovVar->error = -1; - } - return value; -} - -void MGcovParser::GcovReadSummary (struct gcov_summary *summary) { - unsigned ix, h_ix, bv_ix, h_cnt = 0; - struct gcov_ctr_summary *csum; - unsigned histo_bitvector[(252 + 31) / 32]; - unsigned cur_bitvector; - summary->checksum = GcovReadUnsigned(); - for (csum = summary->ctrs, ix = (GCOV_COUNTER_ARCS + 1); ix--; csum++) { - csum->num = GcovReadUnsigned(); - csum->runs = GcovReadUnsigned(); - csum->sum_all = GcovReadCounter(); - csum->run_max = GcovReadCounter(); - csum->sum_max = GcovReadCounter(); - memset_s(csum->histogram, sizeof (gcov_bucket_type) * 252, 0, sizeof (gcov_bucket_type) * 252); - for (bv_ix = 0; bv_ix < (252 + 31) / 32; bv_ix++) { - histo_bitvector[bv_ix] = GcovReadUnsigned(); - h_cnt += popcount_hwi (histo_bitvector[bv_ix]); - } - bv_ix = 0; - h_ix = 0; - cur_bitvector = 0; - while (h_cnt--) { - while (!cur_bitvector) { - h_ix = bv_ix * 32; - if (bv_ix >= (252 + 31) / 32) { - CHECK_FATAL(false, "corrupted profile info: summary histogram " "bitvector is corrupt"); - } - cur_bitvector = histo_bitvector[bv_ix++]; - } - while (!(cur_bitvector & 0x1)) { - h_ix++; - cur_bitvector >>= 1; - } - if (h_ix >= 252) { - CHECK_FATAL(0, "corrupted profile info: summary histogram " "index is corrupt"); - } - csum->histogram[h_ix].num_counters = GcovReadUnsigned(); - csum->histogram[h_ix].min_value = GcovReadCounter(); - csum->histogram[h_ix].cum_value = GcovReadCounter(); - cur_bitvector >>= 1; - h_ix++; - } - } -} - -static unsigned object_runs; -static unsigned program_count; -// reference -int MGcovParser::ReadGcdaFile() { - std::string gcovDataFile = Options::profile; - if (gcovDataFile.empty()) { - if (const char* env_p = std::getenv("GCOV_PREFIX")) { - gcovDataFile.append(env_p); - } else { - gcovDataFile.append("."); - } - gcovDataFile.append("/"); - gcovDataFile.append(m.GetProfileDataFileName()); - } - ASSERT(!gcovDataFile.empty(), "null check"); - if (!GcovOpenFile(gcovDataFile.c_str(), 1)) { - LogInfo::MapleLogger() << "no data file " << gcovDataFile << " \n"; - Options::profileUse = false; // reset profileUse - return 0; - } - - if (!GcovReadMagic(GcovReadUnsigned(), GCOV_DATA_MAGIC)) { - LogInfo::MapleLogger() << gcovDataFile << " not a gcov data file\n"; - GcovCloseFile (); - return 1; - } - unsigned version = GcovReadUnsigned(); - if (version != GCOV_VERSION) { - char v[4], e[4]; - GCOV_UNSIGNED2STRING (v, version); - GCOV_UNSIGNED2STRING (e, GCOV_VERSION); - LogInfo::MapleLogger() << gcovDataFile << " version " << v << " prefer version " << e << "\n"; - } - // read stam value, stamp is generated by time function - // the value should be same in .gcno file but skip compare here - // bbg_stamp - unsigned tag = GcovReadUnsigned(); - - gcovData = localMP->New(&alloc); - GcovFuncInfo *funcInfo = nullptr; - while ((tag = GcovReadUnsigned())) { - unsigned length = GcovReadUnsigned(); - unsigned long base = GcovGetPosition(); - - if (tag == GCOV_TAG_PROGRAM_SUMMARY) { - struct gcov_summary summary; - GcovReadSummary(&summary); - object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs; - program_count++; - } else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH) { - unsigned ident; - /* Try to find the function in the list. To speed up the - search, first start from the last function found. */ - ident = GcovReadUnsigned(); - unsigned lineno_checksum = GcovReadUnsigned(); - unsigned cfg_checksum = GcovReadUnsigned(); - funcInfo = localMP->New(&alloc, ident, lineno_checksum, cfg_checksum); - (gcovData->funcsCounter)[ident] = funcInfo; - } else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS)) { - funcInfo->num_counts = GCOV_TAG_COUNTER_NUM(length); - for (int ix = 0; ix != funcInfo->num_counts; ix++) { - funcInfo->counts.push_back(GcovReadCounter()); - } - } - GcovSync(base, length); - } - GcovCloseFile(); - - if (dumpDetail) { - DumpFuncInfo(); - } - return 0; -} - -void MGcovParser::DumpFuncInfo() { - for (auto &it : gcovData->funcsCounter) { - GcovFuncInfo *funcInfo = it.second; - LogInfo::MapleLogger() << "\nfunction ident " << std::dec << funcInfo->ident; - LogInfo::MapleLogger() << " lino_checksum 0x" << std::hex << funcInfo->lineno_checksum; - LogInfo::MapleLogger() << " cfg_checksum 0x" << std::hex << funcInfo->cfg_checksum << "\n"; - LogInfo::MapleLogger() << " num_counts " << std::dec << funcInfo->num_counts << " : "; - for (int i = 0; i < funcInfo->num_counts; i++) { - LogInfo::MapleLogger() << std::dec << " " << funcInfo->counts[i]; - } - } - LogInfo::MapleLogger() << "\n" ; -} - -void M2MGcovParser::GetAnalysisDependence(AnalysisDep &aDep) const { - aDep.SetPreservedAll(); -} - -bool M2MGcovParser::PhaseRun(maple::MIRModule &m) { - MemPool *memPool = m.GetMemPool(); // use global pool to store gcov data - MGcovParser gcovParser(m, memPool, true); - int res = gcovParser.ReadGcdaFile(); - if (res) { - // something wrong - return false; - } - m.SetGcovProfile(gcovParser.GetGcovData()); - return true; -} - - -} // end namespace maple diff --git a/src/mapleall/mpl2mpl/src/gen_profile.cpp b/src/mapleall/mpl2mpl/src/gen_profile.cpp index 2f1a0bdb0e..cff72a9561 100644 --- a/src/mapleall/mpl2mpl/src/gen_profile.cpp +++ b/src/mapleall/mpl2mpl/src/gen_profile.cpp @@ -104,9 +104,9 @@ void ProfileGen::CreateModProfDesc() { modProfDescSymMirConst->AddItem(checksumMirConst, 5); // Make the profile file name as fileName.gcda - std::string profFileName = mod.GetProfileDataFileName(); + std::string profFileName = mod.GetProfileDataFileName() + namemangler::kProfFileNameExt; auto *profileFNMirConst = - modMP->New("./" + profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); + modMP->New(profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); modProfDescSymMirConst->AddItem(profileFNMirConst, 6); // Additional profiling (in addition to frequency profiling) should be added here diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index 65b2c8d8a9..e0d6984461 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -92,7 +92,7 @@ void MInline::InitParams() { } void MInline::InitProfile() const { - // gcov use different profile data, return + // maple profile use different profile data, return if (Options::profileUse) { return; } @@ -117,7 +117,7 @@ void MInline::InitRCWhiteList() { void MInline::InitExcludedCaller() { std::set specialfunc = { - std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), + std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), }; for (auto it = specialfunc.begin(); it != specialfunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -140,27 +140,40 @@ void MInline::InitExcludedCallee() { (void)excludedCallee.insert(strIdx); } std::set setArrayHotFunc = { - std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_2FObject_3B_29Ljava_2Flang_2FString_3B"), - std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_29Ljava_2Flang_2FObject_3B"), + std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_" + "2FObject_3B_29Ljava_2Flang_2FString_3B"), + std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_" + "2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_" + "29Ljava_2Flang_2FObject_3B"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7Crun_7C_28_29V"), - std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), + std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_" + "7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), std::string("Landroid_2Fview_2Fanimation_2FTransformation_3B_7C_3Cinit_3E_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartOtherServices_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FSettings_3B_7CreadLPw_7C_28Ljava_2Futil_2FList_3B_29Z"), std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CupdateOomAdjLocked_7C_28_29V"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), - std::string("Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_" + "2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), + std::string( + "Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartBootstrapServices_7C_28_29V"), std::string("Ljava_2Flang_2FThrowable_3B_7CgetOurStackTrace_7C_28_29ALjava_2Flang_2FStackTraceElement_3B"), std::string("Ldalvik_2Fsystem_2FVMStack_3B_7CgetStackClass2_7C_28_29Ljava_2Flang_2FClass_3B"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_2Fapp_2FIApplicationThread_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_2FResultReceiver_3B_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_" + "2Fapp_2FIApplicationThread_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_" + "2FResultReceiver_3B_29Z"), }; for (auto it = setArrayHotFunc.begin(); it != setArrayHotFunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -251,7 +264,7 @@ FuncCostResultType MInline::GetFuncCost(const MIRFunction &func, const BaseNode break; } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_customcallassigned: case OP_polymorphiccallassigned: case OP_customcall: @@ -421,17 +434,19 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee LogInfo::MapleLogger() << "[CHECK_HOT] " << callee.GetName() << " to " << caller.GetName() << " op " << callStmt.GetOpCode() << '\n'; } - // use gcov profile + // use maple instrument profile if (Options::profileUse) { - return caller.GetFuncProfData()->IsHotCallSite(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) return false; + int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + ASSERT(freq > 0, "sanity check"); + return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); } return module.GetProfile().CheckFuncHot(caller.GetName()); } bool MInline::FuncInlinable(const MIRFunction &func) const { std::string name = func.GetName(); - if (StringUtils::StartsWith(name, kReflectionClassStr) || - StringUtils::StartsWith(name, kJavaLangClassesStr) || + if (StringUtils::StartsWith(name, kReflectionClassStr) || StringUtils::StartsWith(name, kJavaLangClassesStr) || StringUtils::StartsWith(name, kJavaLangReferenceStr)) { return false; } @@ -686,7 +701,7 @@ static InlineResult GetInlineResult(uint32 threshold, uint32 thresholdType, uint } void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction &callee, const CallNode &callStmt, - uint32 &threshold, uint32 &thresholdType) { + uint32 &threshold, uint32 &thresholdType) { // Update threshold if this callsite is hot, or dealing with recursive function if (inlineWithProfile && IsHotCallSite(caller, callee, callStmt)) { threshold = hotFuncThreshold; @@ -705,9 +720,7 @@ void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction threshold <<= kRelaxThresholdForInlineHint; } // We don't always inline called_once callee to avoid super big caller - if (module.GetSrcLang() == kSrcLangC && - callee.GetAttr(FUNCATTR_called_once) && - callee.GetAttr(FUNCATTR_static)) { + if (module.GetSrcLang() == kSrcLangC && callee.GetAttr(FUNCATTR_called_once) && callee.GetAttr(FUNCATTR_static)) { threshold <<= kRelaxThresholdForCalledOnce; } } diff --git a/src/mapleall/mpl2mpl/src/inline_transformer.cpp b/src/mapleall/mpl2mpl/src/inline_transformer.cpp index d387f64d29..67a3abc455 100644 --- a/src/mapleall/mpl2mpl/src/inline_transformer.cpp +++ b/src/mapleall/mpl2mpl/src/inline_transformer.cpp @@ -307,7 +307,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s dStmt = builder.CreateStmtRegassign(mirPreg->GetPrimType(), pregIdx, currBaseNode); } dStmt->SetSrcPos(stmt.GetSrcPos()); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(dStmt->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); @@ -315,7 +315,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s newBody.ReplaceStmt1WithStmt2(&stmt, dStmt); newBody.InsertAfter(dStmt, gotoNode); } else { - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); } @@ -458,10 +458,9 @@ BlockNode *InlineTransformer::CloneFuncBody(BlockNode &funcBody, bool recursiveF if (callee.IsFromMpltInline()) { return funcBody.CloneTree(theMIRModule->GetCurFuncCodeMPAllocator()); } - if (Options::profileUse) { + if (updateFreq) { auto *callerProfData = caller.GetFuncProfData(); auto *calleeProfData = callee.GetFuncProfData(); - ASSERT(callerProfData && calleeProfData, "nullptr check"); uint64_t callsiteFreq = callerProfData->GetStmtFreq(callStmt.GetStmtID()); uint64_t calleeEntryFreq = calleeProfData->GetFuncFrequency(); uint32_t updateOp = (kKeepOrigFreq | kUpdateFreqbyScale); @@ -562,7 +561,7 @@ void InlineTransformer::AssignActualsToFormals(BlockNode &newBody, uint32 stIdxO CHECK_NULL_FATAL(currBaseNode); CHECK_NULL_FATAL(formal); AssignActualToFormal(newBody, stIdxOff, regIdxOff, *currBaseNode, *formal); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(newBody.GetFirst()->GetStmtID(), callStmt.GetStmtID()); } } @@ -606,7 +605,7 @@ void InlineTransformer::HandleReturn(BlockNode &newBody) { } } } - if (Options::profileUse && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { + if (updateFreq && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } @@ -623,7 +622,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne beginCmt += callee.GetName(); StmtNode *commNode = builder.CreateStmtComment(beginCmt.c_str()); enclosingBlk.InsertBefore(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } // end inlining function @@ -639,7 +638,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne } commNode = builder.CreateStmtComment(endCmt.c_str()); enclosingBlk.InsertAfter(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } CHECK_FATAL(callStmt.GetNext() != nullptr, "null ptr check"); @@ -663,7 +662,7 @@ void InlineTransformer::GenReturnLabel(BlockNode &newBody, uint32 inlinedTimes) // record the created label labelStmt = builder.CreateStmtLabel(returnLabelIdx); newBody.AddStatement(labelStmt); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } diff --git a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp index 375fba0b8d..ff39484443 100644 --- a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp +++ b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp @@ -16,7 +16,7 @@ #include "me_phase_manager.h" #include "ipa_phase_manager.h" #include "ipa_side_effect.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -109,7 +109,7 @@ MAPLE_ANALYSIS_PHASE_REGISTER(M2MCallGraph, callgraph) MAPLE_ANALYSIS_PHASE_REGISTER(M2MKlassHierarchy, classhierarchy) MAPLE_ANALYSIS_PHASE_REGISTER(M2MAnnotationAnalysis, annotationanalysis) MAPLE_ANALYSIS_PHASE_REGISTER(ProfileGenPM, ProfileGenPM) -MAPLE_ANALYSIS_PHASE_REGISTER(M2MGcovParser, gcovparser) +MAPLE_ANALYSIS_PHASE_REGISTER(MMplProfDataParser, grofDataParser) MAPLE_TRANSFORM_PHASE_REGISTER(M2MInline, inline) MAPLE_TRANSFORM_PHASE_REGISTER(M2MIPODevirtualize, ipodevirtulize) diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp new file mode 100644 index 0000000000..95bd0febdd --- /dev/null +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#include "mpl_profdata_parser.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { + +template +T ProfDataBinaryImportBase::ReadNum() { + unsigned numBytesRead = 0; + uint64_t val = namemangler::DecodeULEB128(pos, &numBytesRead); + + pos += numBytesRead; + return static_cast(val); +} + +int ProfileSummaryImport::ReadSummary(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint64_t magicNum = ReadNum(); + if (magicNum != kMapleProfDataMagicNumber) { + LogInfo::MapleLogger() << "magic number error, quit\n"; + return 1; + } + uint64_t checksum = ReadNum(); + uint32_t runtimes = ReadNum(); + uint32_t numofCounts = ReadNum(); + uint64_t maxCount = ReadNum(); + uint64_t sumCount = ReadNum(); + profData->summary.SetSummary(checksum, runtimes, numofCounts, maxCount, sumCount); + uint32_t veclen = ReadNum(); + + for (uint32_t i = 0; i < veclen; i++) { + uint32_t r1 = ReadNum(); + uint32_t r2 = ReadNum(); + uint64_t r3 = ReadNum(); + uint64_t r4 = ReadNum(); + profData->summary.AddHistogramRecord(r1, r2, r3, r4); + } + + return 0; +} + +int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint32_t funcNums = ReadNum(); + if (funcNums == 0) { + return 1; + } + + for (uint32_t i = 0; i < funcNums; i++) { + uint32_t funcIdent = ReadNum(); + uint32_t linocheckSum = ReadNum(); + uint32_t cfgcheckSum = ReadNum(); + uint32_t countNum = ReadNum(); + FuncProfInfo *funcProf = profData->AddNewFuncProfile(funcIdent, linocheckSum, cfgcheckSum, countNum); + CHECK_FATAL(funcProf != nullptr, "nullptr check"); + funcProf->counts.resize(countNum); + for (uint32_t j = 0; j < countNum; j++) { + funcProf->counts[j] = ReadNum(); + } + } + return 0; +} + +int MplProfDataParser::ReadMapleProfileData() { + std::string mprofDataFile = Options::profile; + if (mprofDataFile.empty()) { + if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { + mprofDataFile.append(env_gcovprefix); + if (mprofDataFile.back() != '/') { + mprofDataFile.append("/"); + } + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; + } + uint32_t stripnum = 0; + if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(env_gcovprefixstrip); + stripnum = std::stoi(strip); + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; + } + } + std::string profDataFileName = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "module profdata Name: " << profDataFileName << std::endl; + } + // reduce path in profDataFileName + while (stripnum > 0 && profDataFileName.size() > 1) { + size_t pos = profDataFileName.find_first_of("/", 1); + if (pos == std::string::npos) { + break; + } + profDataFileName = profDataFileName.substr(pos); + stripnum--; + } + if (dumpDetail) { + LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; + } + CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); + mprofDataFile.append(profDataFileName); + } else { + // if gcov_prefix is not set, find .mprofdata according to m.profiledata + mprofDataFile = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "NO ENV, module profdata Name: " << mprofDataFile << std::endl; + } + } + // add .mprofdata + mprofDataFile.append(namemangler::kMplProfFileNameExt); + } + ASSERT(!mprofDataFile.empty(), "null check"); + if (dumpDetail) { + LogInfo::MapleLogger() << "will open mprofileData " << mprofDataFile << std::endl; + } + // create mpl profdata + profData = mempool->New(mempool, &alloc); + // read .mprofdata + std::ifstream inputStream(mprofDataFile, (std::ios::in | std::ios::binary)); + if (!inputStream) { + LogInfo::MapleLogger() << "Could not open the file " << mprofDataFile << "\n"; + return 1; + } + // get length of file + inputStream.seekg(0, std::ios::end); + uint32_t length = inputStream.tellg(); + inputStream.seekg(0, std::ios::beg); + const uint32_t sizeThreshold = 1024 * 10; + CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); + + std::unique_ptr buffer = std::make_unique(length); + inputStream.read(buffer.get(), length); + inputStream.close(); + // read 1st part summary + ProfileSummaryImport summaryImport(mprofDataFile, inputStream); + summaryImport.SetPosition((uint8_t*)(buffer.get())); + int res = summaryImport.ReadSummary(profData); + if (res) { + LogInfo::MapleLogger() << "no summary part\n"; + return 1; + } + if (dumpDetail) { + profData->summary.DumpSummary(); + } + // read 2nd part function profile data + FunctionProfileImport funcImport(mprofDataFile, inputStream); + funcImport.SetPosition(summaryImport.GetPosition()); + res = funcImport.ReadFuncProfile(profData); + if (res) { + LogInfo::MapleLogger() << "no function profile part\n"; + return 1; + } + if (dumpDetail) { + profData->DumpFunctionsProfile(); + } + return 0; +} + +void MMplProfDataParser::GetAnalysisDependence(AnalysisDep &aDep) const { + aDep.SetPreservedAll(); +} + +bool MMplProfDataParser::PhaseRun(maple::MIRModule &m) { + MemPool *memPool = m.GetMemPool(); // use global pool to store profile data + bool enableDebug = true; // true to dump trace + MplProfDataParser parser(m, memPool, enableDebug); + int res = parser.ReadMapleProfileData(); + if (res) { + // something wrong + LogInfo::MapleLogger() << " parse .mprofdata error\n"; + return false; + } + m.SetMapleProfile(parser.GetProfData()); + + return true; +} + +} // end namespace maple -- Gitee From 412e0fa3edc12e57240b3ece83458eafcf3145f1 Mon Sep 17 00:00:00 2001 From: fye Date: Thu, 11 Aug 2022 08:57:58 -0700 Subject: [PATCH 2/7] profuse: ~170+~60+2 fixes for warnings from CI tools --- src/mapleall/maple_ir/include/mir_module.h | 10 +-- .../maple_me/include/me_loop_unrolling.h | 3 +- src/mapleall/maple_me/src/bb.cpp | 26 +++--- src/mapleall/maple_me/src/hdse.cpp | 11 +-- src/mapleall/maple_me/src/me_cfg.cpp | 50 +++++------ src/mapleall/maple_me/src/me_loop_canon.cpp | 67 +++++++-------- .../maple_me/src/me_loop_inversion.cpp | 4 +- src/mapleall/maple_me/src/me_profile_use.cpp | 4 +- .../maple_me/src/me_value_range_prop.cpp | 83 ++++++++++--------- src/mapleall/maple_me/src/optimizeCFG.cpp | 17 ++-- src/mapleall/maple_util/include/namemangler.h | 2 +- src/mapleall/maple_util/src/mpl_profdata.cpp | 19 +++-- src/mapleall/maple_util/src/namemangler.cpp | 44 +++++----- src/mapleall/mpl2mpl/src/inline.cpp | 6 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 26 +++--- 15 files changed, 190 insertions(+), 182 deletions(-) diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index f5965f008d..700b022338 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -342,12 +342,12 @@ class MIRModule { std::string GetProfileDataFileName() const { std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); - char *gcov_path = std::getenv("GCOV_PREFIX"); - std::string gcov_prefix = gcov_path ? gcov_path : ""; - if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { - gcov_prefix.append("/"); + const char *gcovPath = std::getenv("GCOV_PREFIX"); + std::string gcovPrefix = gcovPath ? gcovPath : ""; + if (!gcovPrefix.empty() && (gcovPrefix.back() != '/')) { + gcovPrefix.append("/"); } - profileDataFileName = gcov_prefix + profileDataFileName; + profileDataFileName = gcovPrefix + profileDataFileName; return profileDataFileName; } diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 1e5f57be8f..fe36d56e73 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -29,8 +29,7 @@ constexpr uint32 kMaxCost = 100; constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll - { + enum ReturnKindOfFullyUnroll { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 290a3c6caa..1096c836d9 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,9 +13,6 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" - -#include - #include "me_ir.h" #include "me_ssa.h" #include "mempool_allocator.h" @@ -83,7 +80,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse && frequency >= 0) { + // if (Options::profileUse && frequency >= 0) { + if (Options::profileUse) { mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; @@ -487,21 +485,19 @@ void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - int diff = abs(succFreqs - GetFrequency()); - if (len == 0 || diff <= 1) return; - int64_t scaledSum = 0; - for (int i = 0; i < len; i++) { - int64_t sfreq = GetSuccFreq()[i]; + int diff = static_cast(abs(succFreqs - GetFrequency())); + if (len == 0 || diff <= 1) {return;} + for (uint32 i = 0; i < len; i++) { + int64_t sfreq = GetSuccFreq()[static_cast(i)]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); - scaledSum += scalefreq; - SetSuccFreq(i, scalefreq); + SetSuccFreq(static_cast(i), scalefreq); // update succ frequency with new difference if needed if (updateBBFreqOfSucc) { - auto *succ = GetSucc(i); - int64_t diff = scalefreq - sfreq; - int64_t succBBnewFreq = succ->GetFrequency() + diff; + auto *succBBLoc = GetSucc(static_cast(i)); + int64_t diffFreq = scalefreq - sfreq; + int64_t succBBnewFreq = succBBLoc->GetFrequency() + diffFreq; if (succBBnewFreq >= 0) { - succ->SetFrequency(succBBnewFreq); + succBBLoc->SetFrequency(static_cast(succBBnewFreq)); } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 99748916e6..52c7360992 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -250,11 +250,12 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } bb.SetKind(kBBFallthru); if (UpdateFreq()) { - int64_t succ0Freq = bb.GetSuccFreq()[0]; + int64_t succ0Freq = static_cast(bb.GetSuccFreq()[0]); bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + + (bb.GetFrequency() - succ0Freq))); } } // A ivar contained in stmt @@ -289,7 +290,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().back(); + removedFreq = static_cast(bb.GetSuccFreq().back()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -302,7 +303,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // change to unconditional branch BB *succbb = bb.GetSucc().front(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().front(); + removedFreq = static_cast(bb.GetSuccFreq().front()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -316,7 +317,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { if (UpdateFreq()) { bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + removedFreq)); } } else { DetermineUseCounts(condbr->GetOpnd()); diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index 3b9a752fde..8719578fea 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -1970,9 +1970,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { for (auto *pred : bb->GetPred()) { int idx = pred->GetSuccIndex(*bb); ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); - inputFreq += pred->GetSuccFreq()[idx]; + inputFreq += static_cast(pred->GetSuccFreq()[static_cast(idx)]); } - bb->SetFrequency(inputFreq); + bb->SetFrequency(static_cast(inputFreq)); } // make bb frequency and succs frequency consistent bb->UpdateEdgeFreqs(false); @@ -1984,9 +1984,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { void MeCFG::ClearFuncFreqInfo() { SetUpdateCFGFreq(false); func.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; + auto &bbVecLoc = GetAllBBs(); + for (size_t i = 0; i < bbVecLoc.size(); ++i) { // skip common entry and common exit + auto *bb = bbVecLoc[i]; if (bb == nullptr) { continue; } @@ -1997,7 +1997,7 @@ void MeCFG::ClearFuncFreqInfo() { // return value is 0 means pass verification, else has problem int MeCFG::VerifyBBFreq(bool checkFatal) { - int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + int64_t entryFreq = static_cast(func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency()); ASSERT(entryFreq >= 0, "sanity check"); bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit @@ -2031,19 +2031,20 @@ int MeCFG::VerifyBBFreq(bool checkFatal) { for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } - if (succSumFreq != bb->GetFrequency()) { - int diff = succSumFreq - bb->GetFrequency(); - diff = diff >= 0 ? diff : -diff; - if (diff > 1) { - if (checkFatal) { - LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; - LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq - << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); - } else { - ClearFuncFreqInfo(); - return 1; - } + if (succSumFreq == bb->GetFrequency()) { + continue; + } + int64 diff = static_cast(succSumFreq - bb->GetFrequency()); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; } } } @@ -2088,9 +2089,9 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (theCFG->DumpIRProfileFile()) { std::string fileName = "after-mecfgbuild"; if (f.IsPme()) { - fileName.append("-lfo"); + static_cast(fileName.append("-lfo")); } else { - fileName.append("-mplme"); + static_cast(fileName.append("-mplme")); } theCFG->DumpToFile(fileName, false, true); } @@ -2101,13 +2102,14 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { // if transform pass is not fully support, set disableFreqInfo to true // function profile information will be deleted after verification phase - bool disableFreqInfo = false; if (f.GetCfg()->UpdateCFGFreq()) { - f.GetCfg()->VerifyBBFreq(); + static_cast(f.GetCfg()->VerifyBBFreq()); } - if (!disableFreqInfo) return false; +#ifdef disableFreqInfo + //if (!disableFreqInfo) {return falsea}; // clear function profile information f.GetCfg()->ClearFuncFreqInfo(); +#endif return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 05c4b15f8e..e3f4c6e15d 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -100,8 +100,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - uint64_t freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(freq); + uint64_t freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(freq)); mergedBB->PushBackSuccFreq(freq); } splittedBB->ReplacePred(pred, mergedBB); @@ -134,8 +134,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(mergedBB->GetFrequency() + freq)); } pred->ReplaceSucc(splittedBB, mergedBB); if (updateFreqs) { @@ -254,38 +254,39 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { if (loop.Has(*succ)) { inLoopBBs.push(succ); traveledBBs.insert(succ); - } else { - bool needNewExitBB = false; - for (auto pred : succ->GetPred()) { - if (!loop.Has(*pred)) { - needNewExitBB = true; - break; - } + continue; + } + bool needNewExitBB = false; + for (auto pred : succ->GetPred()) { + if (!loop.Has(*pred)) { + needNewExitBB = true; + break; + } + } + if (needNewExitBB) { + // break the critical edge for code sinking + BB *newExitBB = cfg->NewBasicBlock(); + newExitBB->SetKind(kBBFallthru); + auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + ASSERT(idx >= 0 && idx < curBB->GetSuccFreq().size(), "sanity check"); + freq = curBB->GetSuccFreq()[static_cast(idx)]; + } + curBB->ReplaceSucc(succ, newExitBB); + succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(static_cast(freq)); + newExitBB->PushBackSuccFreq(freq); } - if (needNewExitBB) { - // break the critical edge for code sinking - BB *newExitBB = cfg->NewBasicBlock(); - newExitBB->SetKind(kBBFallthru); - auto pos = succ->GetPredIndex(*curBB); - uint64_t freq = 0; - if (updateFreqs) { - int idx = curBB->GetSuccIndex(*succ); - freq = curBB->GetSuccFreq()[idx]; - } - curBB->ReplaceSucc(succ, newExitBB); - succ->AddPred(*newExitBB, pos); - if (updateFreqs) { - newExitBB->SetFrequency(freq); - newExitBB->PushBackSuccFreq(freq); - } - if (!curBB->GetMeStmts().empty()) { - UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); - } - succ = newExitBB; - isCFGChange = true; + if (!curBB->GetMeStmts().empty()) { + UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } - loop.InsertInloopBB2exitBBs(*curBB, *succ); + succ = newExitBB; + isCFGChange = true; } + loop.InsertInloopBB2exitBBs(*curBB, *succ); } } } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index d3f9505fed..4bef6afb01 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -204,7 +204,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMap exitbb is set 0 // latchBB fallthru is loop exit - int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(0)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(0, bb.GetFrequency()); bb.SetSuccFreq(1, 0); @@ -219,7 +219,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is loop exit, edge frequency of bb ->exitbb is set 0 // latchBB fallthru is in loop - int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(1)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(1, bb.GetFrequency()); bb.SetSuccFreq(0, 0); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 0041c51b0d..6d510e4451 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -372,8 +372,8 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { if (Options::profileUse) { result = profUse.MapleProfRun(); if (result) { - result = f.GetCfg()->VerifyBBFreq(); - if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + result = f.GetCfg()->VerifyBBFreq() != 0 ? true : false; + if (result && (DEBUGFUNC_NEWPM(f))) { LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; } } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index 19425f68fc..a4d884b1f0 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -3140,14 +3140,14 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB int64_t removedFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { int idx = bb.GetSuccIndex(unreachableBB); - removedFreq = bb.GetSuccFreq()[idx]; + removedFreq = static_cast(bb.GetSuccFreq()[static_cast(idx)]); } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); if (func.GetCfg()->UpdateCFGFreq()) { bb.SetSuccFreq(0, bb.GetFrequency()); - succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + succBB.SetFrequency(static_cast(succBB.GetFrequency() + removedFreq)); unreachableBB.SetFrequency(0); } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); @@ -3522,9 +3522,9 @@ void ValueRangePropagation::RemoveUnreachableBB( condGotoBB.SetKind(kBBFallthru); // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + int64_t removedFreq = static_cast(condGotoBB.GetSuccFreq()[1]); condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + succ0->SetFrequency(static_cast(succ0->GetFrequency() + removedFreq)); } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); @@ -3541,12 +3541,12 @@ void ValueRangePropagation::RemoveUnreachableBB( int64_t removedFreq = 0; // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - removedFreq = condGotoBB.GetSuccFreq()[0]; + removedFreq = static_cast(condGotoBB.GetSuccFreq()[0]); } condGotoBB.RemoveSucc(*succ0); if (func.GetCfg()->UpdateCFGFreq()) { condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + succ1->SetFrequency(static_cast(succ1->GetFrequency() + removedFreq)); } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3707,18 +3707,18 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + exitCopyFallthru->SetFrequency(static_cast(exitCopyFallthru->GetFrequency() + edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } return true; @@ -3756,17 +3756,17 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); if (func.GetCfg()->UpdateCFGFreq()) { - mergeAllFallthruBBs->SetFrequency(edgeFreq); - mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + mergeAllFallthruBBs->SetFrequency(static_cast(edgeFreq)); + mergeAllFallthruBBs->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } mergeAllFallthruBBs->AddSucc(trueBranch); @@ -3829,13 +3829,18 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( BB &pred, BB &bb, BB &trueBranch, ScalarMeExpr *updateSSAExceptTheScalarExpr, std::map> &ssaupdateCandsForCondExpr) { CHECK_FATAL(bb.GetKind() == kBBCondGoto, "must be condgoto bb"); - if (GetRealPredSize(bb) >= kNumOperands) { + if (GetRealPredSize(bb) < kNumOperands) { + CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); + RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); + return true; + } + //if (GetRealPredSize(bb) >= kNumOperands) { if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3843,13 +3848,13 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); // transform may not be consistent with frequency value updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); @@ -3858,7 +3863,7 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3866,14 +3871,14 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - exitCopyFallthru->SetFrequency(edgeFreq); - exitCopyFallthru->PushBackSuccFreq(edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + exitCopyFallthru->SetFrequency(static_cast(edgeFreq)); + exitCopyFallthru->PushBackSuccFreq(static_cast(edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); ASSERT(updatedtrueFreq >= 0, "sanity check"); - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } return true; } @@ -3890,27 +3895,27 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); - newBB->SetFrequency(edgeFreq); - newBB->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + newBB->SetFrequency(static_cast(edgeFreq)); + newBB->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); } - } else { - CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); - RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); - } +// } else { +// CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); +// RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); +// } return true; } diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index abbb818c29..7dd3783949 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -712,8 +712,7 @@ class OptimizeBB { bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization // opportunity for currBB after a/some optimization, we should set it true. // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat - { + enum BBErrStat { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -1761,13 +1760,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { int64_t deletedSuccFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = succ.GetSuccIndex(*rmBB); - deletedSuccFreq = succ.GetSuccFreq()[idx]; + deletedSuccFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); } succ.RemoveSucc(*rmBB, true); if (cfg->UpdateCFGFreq()) { succ.SetSuccFreq(0, succ.GetFrequency()); auto *succofSucc = succ.GetSucc(0); - succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + succofSucc->SetFrequency(static_cast(succofSucc->GetFrequency() + deletedSuccFreq)); } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; @@ -1833,9 +1832,9 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; idx = succ.GetSuccIndex(*affectedBB); ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); - int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + int64_t oldedgeFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); ASSERT(oldedgeFreq >= freq, "sanity check"); - succ.SetSuccFreq(idx, (oldedgeFreq - freq)); + succ.SetSuccFreq(idx, static_cast(oldedgeFreq - freq)); } return true; } @@ -2017,13 +2016,13 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { int64_t removedFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*succ); - removedFreq = pred->GetSuccFreq()[idx]; + removedFreq = static_cast(pred->GetSuccFreq()[static_cast(idx)]); } if (pred->IsPredBB(*newTarget)) { pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*newTarget); - pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + pred->SetSuccFreq(idx, static_cast(pred->GetSuccFreq()[static_cast(idx)] + removedFreq)); } } else { pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later @@ -2032,7 +2031,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (cfg->UpdateCFGFreq()) { int64_t succFreq = succ->GetFrequency(); ASSERT(succFreq >= removedFreq, "sanity check"); - succ->SetFrequency(succFreq - removedFreq); + succ->SetFrequency(static_cast(succFreq - removedFreq)); succ->SetSuccFreq(0, succ->GetFrequency()); } DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index c3333b16cf..fdc0f96022 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -213,7 +213,7 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out); uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp index 849b262239..4c65c5496e 100644 --- a/src/mapleall/maple_util/src/mpl_profdata.cpp +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -13,7 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "mpl_profdata.h" - +#include #include "mpl_logging.h" #include "option.h" @@ -55,16 +55,18 @@ void MplProfileData::DumpProfileData() { } void ProfileSummary::ProcessHistogram() { - int countsum = 0; - int n = histogram.size(); - for (int i = n - 1; i >= 0; i--) { - countsum += histogram[i].countNums; - histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + size_t countsum = 0; + size_t n = static_cast(histogram.size()); + enum PERCENTAGE {percent = 100}; + for (int32 i = n - 1; i >= 0; i--) { + countsum += histogram[static_cast(i)].countNums; + histogram[static_cast(i)].countRatio = std::round( + (static_cast(countsum) / static_cast(totalCount)) * percent); } } -#define HOTRATIO 90 uint64_t MplProfileData::GetHotThreshold() { + enum HOTNESS {HOTRATIO = 90}; for (auto &it : summary.GetHistogram()) { if (it.countRatio >= HOTRATIO) { hotCountThreshold = it.startValue; @@ -76,7 +78,8 @@ uint64_t MplProfileData::GetHotThreshold() { } } // should not be here - return 100; + const int unlikelyHot = 100; + return unlikelyHot; } bool MplProfileData::IsHotCallSite(uint64_t freq) { diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index c333420826..150b8c942d 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -597,7 +597,7 @@ size_t GetSleb128Size(int32_t v) { } // encode signed to output stream -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out) { bool more; uint32_t count = 0; do { @@ -631,64 +631,66 @@ uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { // decode a ULEB128 value. uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; uint64_t value = 0; unsigned shift = 0; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } uint64_t slice = *p & 0x7f; - if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if ((shift >= SIXTYFOUR && slice != ZERO) || ((slice << shift) >> shift) != slice) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } value += slice << shift; shift += kGreybackOffset; - } while (*p++ >= 128); + } while (*p++ >= ONEHUNDREDTWENTYEIGHT); if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } // decode a SLEB128 value. int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; int64_t value = 0; unsigned shift = 0; uint8_t byte; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, SIXTYTHREE = 63, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } byte = *p; uint64_t slice = byte & 0x7f; - if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || - (shift == 63 && slice != 0 && slice != 0x7f)) { + if ((shift >= SIXTYFOUR && slice != (value < static_cast(ZERO) ? 0x7f : 0x00)) || + (shift == SIXTYTHREE && slice != ZERO && slice != 0x7f)) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } - value |= slice << shift; + value |= static_cast(slice << shift); shift += kGreybackOffset; ++p; - } while (byte >= 128); + } while (byte >= ONEHUNDREDTWENTYEIGHT); // Sign extend negative numbers if needed. - if (shift < 64 && (byte & 0x40)) { - value |= (-1LL) << shift; + if (shift < SIXTYFOUR && (byte & 0x40)) { + value |= static_cast(0xffffffffffffffff) << shift; } if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index e0d6984461..f3850e2788 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -436,10 +436,10 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee } // use maple instrument profile if (Options::profileUse) { - if (!caller.GetFuncProfData()) return false; - int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) {return false;} + int64_t freq = static_cast(caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID())); ASSERT(freq > 0, "sanity check"); - return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); + return module.GetMapleProfile()->IsHotCallSite(static_cast(freq)); } return module.GetProfile().CheckFuncHot(caller.GetName()); } diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp index 95bd0febdd..b8c73fa36d 100644 --- a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -91,18 +91,18 @@ int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { int MplProfDataParser::ReadMapleProfileData() { std::string mprofDataFile = Options::profile; if (mprofDataFile.empty()) { - if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { - mprofDataFile.append(env_gcovprefix); + if (const char *envGcovprefix = std::getenv("GCOV_PREFIX")) { + static_cast(mprofDataFile.append(envGcovprefix)); if (mprofDataFile.back() != '/') { - mprofDataFile.append("/"); + static_cast(mprofDataFile.append("/")); } if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; } uint32_t stripnum = 0; - if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { - std::string strip(env_gcovprefixstrip); - stripnum = std::stoi(strip); + if (const char *envGcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(envGcovprefixstrip); + stripnum = static_cast(std::stoi(strip)); if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; } @@ -124,7 +124,7 @@ int MplProfDataParser::ReadMapleProfileData() { LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; } CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); - mprofDataFile.append(profDataFileName); + static_cast(mprofDataFile.append(profDataFileName)); } else { // if gcov_prefix is not set, find .mprofdata according to m.profiledata mprofDataFile = m.GetProfileDataFileName(); @@ -133,7 +133,7 @@ int MplProfDataParser::ReadMapleProfileData() { } } // add .mprofdata - mprofDataFile.append(namemangler::kMplProfFileNameExt); + static_cast(mprofDataFile.append(namemangler::kMplProfFileNameExt)); } ASSERT(!mprofDataFile.empty(), "null check"); if (dumpDetail) { @@ -148,18 +148,18 @@ int MplProfDataParser::ReadMapleProfileData() { return 1; } // get length of file - inputStream.seekg(0, std::ios::end); - uint32_t length = inputStream.tellg(); - inputStream.seekg(0, std::ios::beg); + static_cast(inputStream.seekg(0, std::ios::end)); + uint32_t length = static_cast(inputStream.tellg()); + static_cast(inputStream.seekg(0, std::ios::beg)); const uint32_t sizeThreshold = 1024 * 10; CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); std::unique_ptr buffer = std::make_unique(length); - inputStream.read(buffer.get(), length); + static_cast(inputStream.read(buffer.get(), length)); inputStream.close(); // read 1st part summary ProfileSummaryImport summaryImport(mprofDataFile, inputStream); - summaryImport.SetPosition((uint8_t*)(buffer.get())); + summaryImport.SetPosition(reinterpret_cast(buffer.get())); int res = summaryImport.ReadSummary(profData); if (res) { LogInfo::MapleLogger() << "no summary part\n"; -- Gitee From 989d7b015dc02a7d1121ce8bd44713eb3d4e2f9b Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 3 Aug 2022 14:45:17 -0700 Subject: [PATCH 3/7] Switch to using maple profile data file format; update frequences in various maple_me phases --- src/mapleall/maple_ipa/src/ipa_clone.cpp | 4 +- .../maple_ipa/src/ipa_phase_manager.cpp | 6 +- src/mapleall/maple_ir/include/mir_function.h | 8 +- src/mapleall/maple_ir/include/mir_lower.h | 2 +- src/mapleall/maple_ir/include/mir_module.h | 24 +- src/mapleall/maple_ir/src/mir_nodes.cpp | 21 +- src/mapleall/maple_me/include/bb.h | 33 +- src/mapleall/maple_me/include/hdse.h | 21 +- src/mapleall/maple_me/include/me_cfg.h | 39 +- src/mapleall/maple_me/include/me_loop_canon.h | 5 +- .../maple_me/include/me_loop_unrolling.h | 52 ++- .../maple_me/include/me_profile_use.h | 5 +- src/mapleall/maple_me/include/pme_emit.h | 2 +- src/mapleall/maple_me/src/bb.cpp | 43 ++- src/mapleall/maple_me/src/hdse.cpp | 59 ++- src/mapleall/maple_me/src/me_bb_layout.cpp | 84 +++-- src/mapleall/maple_me/src/me_cfg.cpp | 251 ++++++++----- .../maple_me/src/me_critical_edge.cpp | 22 +- src/mapleall/maple_me/src/me_dse.cpp | 10 +- src/mapleall/maple_me/src/me_hdse.cpp | 23 +- src/mapleall/maple_me/src/me_loop_canon.cpp | 60 ++- .../maple_me/src/me_loop_inversion.cpp | 112 +++--- .../maple_me/src/me_loop_unrolling.cpp | 165 ++++---- src/mapleall/maple_me/src/me_profile_use.cpp | 49 ++- .../maple_me/src/me_value_range_prop.cpp | 103 +++++ src/mapleall/maple_me/src/optimizeCFG.cpp | 354 ++++++++++-------- src/mapleall/maple_util/BUILD.gn | 1 + .../maple_util/include/mpl_profdata.h | 203 ++++++++++ src/mapleall/maple_util/include/namemangler.h | 5 + src/mapleall/maple_util/src/mpl_profdata.cpp | 100 +++++ src/mapleall/maple_util/src/namemangler.cpp | 105 +++++- src/mapleall/mpl2mpl/BUILD.gn | 2 +- src/mapleall/mpl2mpl/include/gcov_parser.h | 117 ------ .../mpl2mpl/include/inline_transformer.h | 5 +- .../mpl2mpl/include/mpl_profdata_parser.h | 118 ++++++ src/mapleall/mpl2mpl/src/call_graph.cpp | 40 +- src/mapleall/mpl2mpl/src/gen_profile.cpp | 4 +- src/mapleall/mpl2mpl/src/inline.cpp | 61 +-- .../mpl2mpl/src/inline_transformer.cpp | 17 +- .../mpl2mpl/src/module_phase_manager.cpp | 4 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 204 ++++++++++ 41 files changed, 1799 insertions(+), 744 deletions(-) create mode 100644 src/mapleall/maple_util/include/mpl_profdata.h create mode 100644 src/mapleall/maple_util/src/mpl_profdata.cpp delete mode 100644 src/mapleall/mpl2mpl/include/gcov_parser.h create mode 100644 src/mapleall/mpl2mpl/include/mpl_profdata_parser.h create mode 100644 src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp diff --git a/src/mapleall/maple_ipa/src/ipa_clone.cpp b/src/mapleall/maple_ipa/src/ipa_clone.cpp index ff25da0c85..9b32d5cc3a 100644 --- a/src/mapleall/maple_ipa/src/ipa_clone.cpp +++ b/src/mapleall/maple_ipa/src/ipa_clone.cpp @@ -140,9 +140,9 @@ MIRFunction *IpaClone::IpaCloneFunctionWithFreq(MIRFunction &originalFunction, newFunc->SetBaseClassFuncNames(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(fullName)); newFunc->GetFuncSymbol()->SetAppearsInCode(true); newFunc->SetPuidxOrigin(newFunc->GetPuidx()); - GcovFuncInfo *origProfData = originalFunction.GetFuncProfData(); + FuncProfInfo *origProfData = originalFunction.GetFuncProfData(); auto *moduleMp = mirBuilder.GetMirModule().GetMemPool(); - GcovFuncInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), + FuncProfInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), newFunc->GetPuidx(), 0, 0); // skip checksum information newFunc->SetFuncProfData(newProfData); newProfData->SetFuncFrequency(callSiteFreq); diff --git a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp index b3fc2d7ba2..f477c8fa90 100644 --- a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp +++ b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp @@ -14,7 +14,7 @@ */ #include "ipa_phase_manager.h" #include "pme_emit.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -102,8 +102,8 @@ void IpaSccPM::GetAnalysisDependence(maple::AnalysisDep &aDep) const { aDep.AddPreserved(); aDep.AddPreserved(); if (Options::profileUse) { - aDep.AddRequired(); - aDep.AddPreserved(); + aDep.AddRequired(); + aDep.AddPreserved(); } } diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 161611f558..4b1a08acfb 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1271,13 +1271,13 @@ class MIRFunction { InlineSummary *GetOrCreateInlineSummary(); - void SetFuncProfData(GcovFuncInfo *data) { + void SetFuncProfData(FuncProfInfo *data) { funcProfData = data; } - GcovFuncInfo* GetFuncProfData() { + FuncProfInfo* GetFuncProfData() { return funcProfData; } - GcovFuncInfo* GetFuncProfData() const { + FuncProfInfo* GetFuncProfData() const { return funcProfData; } void SetStmtFreq(uint32_t stmtID, uint64_t freq) { @@ -1402,7 +1402,7 @@ class MIRFunction { uint32 nCtrs = 0; // number of counters uint64 fileLinenoChksum = 0; uint64 cfgChksum = 0; - GcovFuncInfo *funcProfData = nullptr; + FuncProfInfo *funcProfData = nullptr; InlineSummary *inlineSummary = nullptr; void DumpFlavorLoweredThanMmpl() const; MIRFuncType *ReconstructFormals(const std::vector &symbols, bool clearOldArgs); diff --git a/src/mapleall/maple_ir/include/mir_lower.h b/src/mapleall/maple_ir/include/mir_lower.h index c2261326d1..e4229aa853 100644 --- a/src/mapleall/maple_ir/include/mir_lower.h +++ b/src/mapleall/maple_ir/include/mir_lower.h @@ -142,7 +142,7 @@ class MIRLower { virtual bool InLFO() const { return false; } - GcovFuncInfo *GetFuncProfData() const { + FuncProfInfo *GetFuncProfData() const { return mirFunc->GetFuncProfData(); } void CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt) { diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index 37c54a99b3..f5965f008d 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -22,7 +22,7 @@ #include "muid.h" #include "profile.h" #include "namemangler.h" -#include "gcov_profile.h" +#include "mpl_profdata.h" #if MIR_FEATURE_FULL #include #include @@ -268,11 +268,11 @@ class MIRModule { return profile; } - GcovProfileData* GetGcovProfile() { - return gcovProfile; + MplProfileData* GetMapleProfile() { + return mplProfile; } - void SetGcovProfile(GcovProfileData* info) { - gcovProfile = info; + void SetMapleProfile(MplProfileData* info) { + mplProfile = info; } void SetSomeSymbolNeedForDecl(bool s) { @@ -341,11 +341,13 @@ class MIRModule { } std::string GetProfileDataFileName() const { - std::string profileDataFileName = fileName.substr(0, fileName.find_last_of(".")); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '.', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '-', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '/', '_'); - profileDataFileName = profileDataFileName + namemangler::kProfFileNameExt; + std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); + char *gcov_path = std::getenv("GCOV_PREFIX"); + std::string gcov_prefix = gcov_path ? gcov_path : ""; + if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { + gcov_prefix.append("/"); + } + profileDataFileName = gcov_prefix + profileDataFileName; return profileDataFileName; } @@ -710,7 +712,7 @@ class MIRModule { MapleSet symbolSet; MapleVector symbolDefOrder; Profile profile; - GcovProfileData* gcovProfile; + MplProfileData* mplProfile; bool someSymbolNeedForwDecl = false; // some symbols' addressses used in initialization std::ostream &out; diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index e8113fb657..fbdd3bae68 100644 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -686,10 +686,11 @@ void AddroflabelNode::Dump(int32 indent [[maybe_unused]]) const { void StmtNode::DumpBase(int32 indent) const { srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs - if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData() && - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) >= 0) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } PrintIndentation(indent); LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name; @@ -1329,8 +1330,10 @@ void BlockNode::Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } for (auto &stmt : GetStmtNodes()) { stmt.Dump(indent + 1); @@ -1345,8 +1348,10 @@ void LabelNode::Dump(int32 indent [[maybe_unused]]) const { } // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } LogInfo::MapleLogger() << "@" << theMIRModule->CurFunction()->GetLabelName(labelIdx) << " "; } diff --git a/src/mapleall/maple_me/include/bb.h b/src/mapleall/maple_me/include/bb.h index 24d5327261..e0c01e71e8 100644 --- a/src/mapleall/maple_me/include/bb.h +++ b/src/mapleall/maple_me/include/bb.h @@ -14,18 +14,18 @@ */ #ifndef MAPLE_ME_INCLUDE_BB_H #define MAPLE_ME_INCLUDE_BB_H -#include "utils.h" #include "mpl_number.h" -#include "ptr_list_ref.h" #include "orig_symbol.h" -#include "ver_symbol.h" +#include "ptr_list_ref.h" #include "ssa.h" +#include "utils.h" +#include "ver_symbol.h" namespace maple { -class MeStmt; // circular dependency exists, no other choice -class MePhiNode; // circular dependency exists, no other choice +class MeStmt; // circular dependency exists, no other choice +class MePhiNode; // circular dependency exists, no other choice class PiassignMeStmt; // circular dependency exists, no other choice -class IRMap; // circular dependency exists, no other choice +class IRMap; // circular dependency exists, no other choice enum BBKind { kBBUnknown, // uninitialized kBBCondGoto, @@ -406,8 +406,17 @@ class BB { ASSERT(idx >= 0 && idx <= succFreq.size(), "sanity check"); succFreq[static_cast(idx)] = freq; } + void AddSuccFreq(uint64 freq, size_t pos = UINT32_MAX) { + ASSERT((pos <= succFreq.size() || pos == UINT32_MAX), "Invalid position."); + if (pos == UINT32_MAX) { + succFreq.push_back(freq); + } else { + succFreq.insert(succFreq.begin() + pos, freq); + } + } + // update edge frequency - void UpdateEdgeFreqs(); + void UpdateEdgeFreqs(bool updateSuccFreq = true); const MapleVector &GetSucc() const { return succ; @@ -487,7 +496,7 @@ class BB { auto iter = std::find(succ.begin(), succ.end(), bb); CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d", succFreq.size(), - succ.size()); + succ.size()); const size_t idx = static_cast(std::distance(succ.begin(), iter)); succFreq[idx] = freq; } @@ -496,7 +505,7 @@ class BB { succFreq.resize(succ.size()); } - BB* GetGroup() const { + BB *GetGroup() const { return group; } @@ -524,12 +533,13 @@ class BB { int GetPredIndex(const BB &predBB) const; int GetSuccIndex(const BB &succBB) const; void RemovePhiOpnd(int index); + private: bool IsInList(const MapleVector &bbList) const; int RemoveBBFromVector(MapleVector &bbVec) const; BBId id; - LabelIdx bbLabel = 0; // the BB's label + LabelIdx bbLabel = 0; // the BB's label MapleVector pred; // predecessor list MapleVector succ; // successor list // record the edge freq from curBB to succ BB @@ -540,8 +550,10 @@ class BB { uint32 frequency = 0; BBKind kind = kBBUnknown; uint32 attributes = 0; + public: StmtNodes stmtNodeList; + private: MeStmts meStmtList; BB *group; @@ -586,6 +598,7 @@ class SCCOfBBs { BB *GetEntry() { return entry; } + private: uint32 id; BB *entry; diff --git a/src/mapleall/maple_me/include/hdse.h b/src/mapleall/maple_me/include/hdse.h index c5a637c314..a00188d9c5 100644 --- a/src/mapleall/maple_me/include/hdse.h +++ b/src/mapleall/maple_me/include/hdse.h @@ -14,17 +14,17 @@ */ #ifndef MAPLE_ME_INCLUDE_HDSE_H #define MAPLE_ME_INCLUDE_HDSE_H +#include "alias_class.h" #include "bb.h" -#include "irmap.h" #include "dominance.h" -#include "alias_class.h" +#include "irmap.h" namespace maple { class MeIRMap; class HDSE { public: - HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, - Dominance &pDom, IRMap &map, const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) + HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, Dominance &pDom, IRMap &map, + const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) : hdseDebug(enabledDebug), mirModule(mod), bbVec(bbVec), @@ -48,6 +48,12 @@ class HDSE { void SetRemoveRedefine(bool val) { removeRedefine = val; } + void SetUpdateFreq(bool update) { + updateFreq = update; + } + bool UpdateFreq() { + return updateFreq; + } bool hdseDebug; bool hdseKeepRef = false; @@ -73,10 +79,11 @@ class HDSE { // Or the meExpr is opnd of a same type meExpr static const uint8 kExprTypeNotNull = 2; bool decoupleStatic = false; - bool needUNClean = false; // used to record if there's unreachable BB + bool needUNClean = false; // used to record if there's unreachable BB bool removeRedefine = false; // used to control if run ResolveContinuousRedefine() - MapleVector verstUseCounts; // index is vstIdx - std::forward_list backSubsCands; // backward substitution candidates + bool updateFreq = false; + MapleVector verstUseCounts; // index is vstIdx + std::forward_list backSubsCands; // backward substitution candidates private: void DseInit(); diff --git a/src/mapleall/maple_me/include/me_cfg.h b/src/mapleall/maple_me/include/me_cfg.h index d04e9addb1..8465e37e75 100644 --- a/src/mapleall/maple_me/include/me_cfg.h +++ b/src/mapleall/maple_me/include/me_cfg.h @@ -14,12 +14,13 @@ */ #ifndef MAPLE_ME_INCLUDE_ME_CFG_H #define MAPLE_ME_INCLUDE_ME_CFG_H -#include "me_function.h" #include "maple_phase.h" +#include "me_function.h" namespace maple { class MeCFG : public AnalysisResult { using BBPtrHolder = MapleVector; + public: using value_type = BBPtrHolder::value_type; using size_type = BBPtrHolder::size_type; @@ -86,7 +87,9 @@ class MeCFG : public AnalysisResult { hasDoWhile = hdw; } - MapleAllocator &GetAlloc() { return mecfgAlloc; } + MapleAllocator &GetAlloc() { + return mecfgAlloc; + } void SetNextBBId(uint32 currNextBBId) { nextBBId = currNextBBId; @@ -98,7 +101,9 @@ class MeCFG : public AnalysisResult { --nextBBId; } - MapleVector &GetAllBBs() { return bbVec; } + MapleVector &GetAllBBs() { + return bbVec; + } iterator begin() { return bbVec.begin(); @@ -296,8 +301,19 @@ class MeCFG : public AnalysisResult { void ConstructBBFreqFromStmtFreq(); void ConstructStmtFreq(); void ConstructEdgeFreqFromBBFreq(); - void UpdateEdgeFreqWithNewBBFreq(); - void VerifyBBFreq(); + void UpdateEdgeFreqWithBBFreq(); + int VerifyBBFreq(bool checkFatal = false); + void SetUpdateCFGFreq(bool b) { + updateFreq = b; + } + bool UpdateCFGFreq() const { + return updateFreq; + } + bool DumpIRProfileFile() const { + return dumpIRProfileFile; + } + void ClearFuncFreqInfo(); + private: void AddCatchHandlerForTryBB(BB &bb, MapleVector &exitBlocks); std::string ConstructFileNameToDump(const std::string &prefix) const; @@ -316,11 +332,14 @@ class MeCFG : public AnalysisResult { MapleAllocator mecfgAlloc; MeFunction &func; MapleSet patternSet; - BBPtrHolder bbVec; + BBPtrHolder bbVec; MapleUnorderedMap labelBBIdMap; MapleUnorderedMap bbTryNodeMap; // maps isTry bb to its try stmt MapleUnorderedMap endTryBB2TryBB; // maps endtry bb to its try bb bool hasDoWhile = false; + // following 2 variable are used in profileUse + bool updateFreq = false; // true to maintain cfg frequency in transform phase + bool dumpIRProfileFile = false; // true to dump cfg to files uint32 nextBBId = 0; // BB SCC @@ -331,10 +350,10 @@ class MeCFG : public AnalysisResult { }; MAPLE_FUNC_PHASE_DECLARE_BEGIN(MEMeCfg, MeFunction) - MeCFG *GetResult() { - return theCFG; - } - MeCFG *theCFG = nullptr; +MeCFG *GetResult() { + return theCFG; +} +MeCFG *theCFG = nullptr; MAPLE_MODULE_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(MECfgVerifyFrequency, MeFunction) MAPLE_FUNC_PHASE_DECLARE_END diff --git a/src/mapleall/maple_me/include/me_loop_canon.h b/src/mapleall/maple_me/include/me_loop_canon.h index 248a185127..cd76626574 100644 --- a/src/mapleall/maple_me/include/me_loop_canon.h +++ b/src/mapleall/maple_me/include/me_loop_canon.h @@ -21,7 +21,8 @@ namespace maple { // convert loop to do-while format class MeLoopCanon { public: - MeLoopCanon(MeFunction &f, bool enableDebugFunc) : func(f), isDebugFunc(enableDebugFunc) {} + MeLoopCanon(MeFunction &f, bool enableDebugFunc, bool updateFreq) + : func(f), isDebugFunc(enableDebugFunc), updateFreqs(updateFreq) {} virtual ~MeLoopCanon() = default; void NormalizationExitOfLoop(IdentifyLoops &meLoop); void NormalizationHeadAndPreHeaderOfLoop(Dominance &dom); @@ -33,6 +34,7 @@ class MeLoopCanon { void ResetIsCFGChange() { isCFGChange = false; } + private: void FindHeadBBs(Dominance &dom, const BB *bb, std::map> &heads) const; void SplitPreds(const std::vector &splitList, BB *splittedBB, BB *mergedBB); @@ -44,6 +46,7 @@ class MeLoopCanon { MeFunction &func; bool isDebugFunc; bool isCFGChange = false; + bool updateFreqs = false; }; MAPLE_FUNC_PHASE_DECLARE(MELoopCanon, MeFunction) diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 4b0c81c075..1e5f57be8f 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -14,22 +14,23 @@ */ #ifndef MAPLE_ME_INCLUDE_LOOP_UNROLLING_H #define MAPLE_ME_INCLUDE_LOOP_UNROLLING_H -#include "me_scalar_analysis.h" +#include "me_cfg.h" +#include "me_dominance.h" #include "me_function.h" -#include "me_irmap_build.h" #include "me_ir.h" -#include "me_ssa_update.h" -#include "me_dominance.h" +#include "me_irmap_build.h" #include "me_loop_analysis.h" +#include "me_scalar_analysis.h" +#include "me_ssa_update.h" #include "profile.h" -#include "me_cfg.h" namespace maple { constexpr uint32 kMaxCost = 100; -constexpr uint8 unrollTimes[3] = { 8, 4, 2 }; // unrollTimes +constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll { + enum ReturnKindOfFullyUnroll + { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, @@ -37,14 +38,26 @@ class LoopUnrolling { LoopUnrolling(MeFunction &f, LoopDesc &l, MeIRMap &map, const MapleAllocator &alloc, std::map>> &candsTemp) - : func(&f), cfg(f.GetCfg()), loop(&l), irMap(&map), mpAllocator(alloc), - cands(candsTemp), lastNew2OldBB(mpAllocator.Adapter()), + : func(&f), + cfg(f.GetCfg()), + loop(&l), + irMap(&map), + mpAllocator(alloc), + cands(candsTemp), + lastNew2OldBB(mpAllocator.Adapter()), profValid(func->IsIRProfValid()) {} ~LoopUnrolling() = default; ReturnKindOfFullyUnroll LoopFullyUnroll(int64 tripCount); bool LoopPartialUnrollWithConst(uint64 tripCount); bool LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j); bool LoopUnrollingWithConst(uint64 tripCount, bool onlyFully = false); + void SetInstrumentProf(bool useInstrument) { + instrumentProf = useInstrument; + profValid = useInstrument; + } + bool GetInstrumentProf() const { + return instrumentProf; + } private: bool SplitCondGotoBB(); @@ -53,14 +66,12 @@ class LoopUnrolling { void SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, const BB &exitBB, LabelIdx oldlabIdx); - void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); - void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); + void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); + void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); void UpdateCondGotoBB(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr); void UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, uint32 offset); void CreateIndVarAndCondGotoStmt(CR &cr, CRNode &varNode, BB &preCondGoto, uint32 unrollTime, uint32 i); @@ -85,7 +96,7 @@ class LoopUnrolling { bool canUnroll = true; MeFunction *func; - MeCFG *cfg; + MeCFG *cfg; LoopDesc *loop; MeIRMap *irMap; MapleAllocator mpAllocator; @@ -100,6 +111,7 @@ class LoopUnrolling { bool firstResetForAfterInsertGoto = true; bool resetFreqForUnrollWithVar = false; bool isUnrollWithVar = false; + bool instrumentProf = false; // use instrumented profiling }; class LoopUnrollingExecutor { @@ -109,8 +121,8 @@ class LoopUnrollingExecutor { static bool enableDebug; static bool enableDump; - void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc); + void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc); bool IsCFGChange() const { return isCFGChange; } diff --git a/src/mapleall/maple_me/include/me_profile_use.h b/src/mapleall/maple_me/include/me_profile_use.h index a6a0be8df7..2014e80026 100644 --- a/src/mapleall/maple_me/include/me_profile_use.h +++ b/src/mapleall/maple_me/include/me_profile_use.h @@ -137,8 +137,7 @@ class MeProfUse : public PGOInstrument { bool IsSuccUseProf() const { return succCalcuAllEdgeFreq; } - bool GcovRun(); - GcovFuncInfo *GetFuncData(); + bool MapleProfRun(); bool CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, const std::string &tag); private: bool IsAllZero(Profile::BBInfo &result) const; @@ -147,6 +146,8 @@ class MeProfUse : public PGOInstrument { void ComputeEdgeFreq(); void InitBBEdgeInfo(); void ComputeBBFreq(BBUseInfo &bbInfo, bool &changed); + FuncProfInfo *GetFuncData(); + uint64 SumEdgesCount(const MapleVector &edges) const; BBUseInfo *GetBBUseInfo(const BB &bb) const; BBUseInfo *GetOrCreateBBUseInfo(const BB &bb) ; diff --git a/src/mapleall/maple_me/include/pme_emit.h b/src/mapleall/maple_me/include/pme_emit.h index 85cb7996ec..e9a4628409 100644 --- a/src/mapleall/maple_me/include/pme_emit.h +++ b/src/mapleall/maple_me/include/pme_emit.h @@ -79,7 +79,7 @@ class PreMeEmitter : public AnalysisResult { MapleAllocator* GetCodeMPAlloc() { return codeMPAlloc; } MapleMap *GetPreMeStmtExtensionMap() { return &preMeStmtExtensionMap; } MapleMap *GetPreMeExprExtensionMap() { return &preMeExprExtensionMap; } - GcovFuncInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } + FuncProfInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } private: ArrayNode *ConvertToArray(BaseNode *x, TyIdx ptrTyIdx); diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 7e7e7e5490..290a3c6caa 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,10 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" + +#include + +#include "me_ir.h" +#include "me_ssa.h" #include "mempool_allocator.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "me_ir.h" namespace maple { std::string BB::StrAttribute() const { @@ -80,8 +83,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse) { - mod->GetOut() << " freq: " << frequency << " "; + if (Options::profileUse && frequency >= 0) { + mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; mod->GetOut() << "preds: "; @@ -299,8 +302,8 @@ void BB::MoveAllPredToSucc(BB *newSucc, BB *commonEntry) { } 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 + if (IsSuccBB(*firstPred)) { // avoid replacing twice + firstPred->ReplaceSucc(this, newSucc, true); // firstPred will be removed from this->pred } } } @@ -336,8 +339,8 @@ void BB::MoveAllSuccToPred(BB *newPred, BB *commonExit) { } else { while (!GetSucc().empty()) { BB *firstSucc = GetSucc(0); - if (IsPredBB(*firstSucc)) { // avoid replacing twice - firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ + if (IsPredBB(*firstSucc)) { // avoid replacing twice + firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ } } } @@ -476,23 +479,31 @@ void BB::DumpMePhiList(const IRMap *irMap) { } } -// bb frequency is changed in tranform phase -// update its succ frequency by scaled value -void BB::UpdateEdgeFreqs() { +// update edge frequency by scaled value when bb frequency is changed +void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { int len = GetSucc().size(); ASSERT(len == GetSuccFreq().size(), "sanity check"); int64_t succFreqs = 0; for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - // early return if frequency is consistent - if (len == 0 || succFreqs == GetFrequency()) { - return; - } - for (size_t i = 0; i < len; ++i) { + int diff = abs(succFreqs - GetFrequency()); + if (len == 0 || diff <= 1) return; + int64_t scaledSum = 0; + for (int i = 0; i < len; i++) { int64_t sfreq = GetSuccFreq()[i]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); + scaledSum += scalefreq; SetSuccFreq(i, scalefreq); + // update succ frequency with new difference if needed + if (updateBBFreqOfSucc) { + auto *succ = GetSucc(i); + int64_t diff = scalefreq - sfreq; + int64_t succBBnewFreq = succ->GetFrequency() + diff; + if (succBBnewFreq >= 0) { + succ->SetFrequency(succBBnewFreq); + } + } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 4badba2ad5..99748916e6 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -13,20 +13,22 @@ * See the Mulan PSL v2 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 "opcode_info.h" +#include "ssa_mir_nodes.h" #include "utils.h" +#include "ver_symbol.h" namespace maple { using namespace utils; void HDSE::DetermineUseCounts(MeExpr *x) { if (x->GetMeOp() == kMeOpVar) { - VarMeExpr *varmeexpr = static_cast(x); + VarMeExpr *varmeexpr = static_cast(x); verstUseCounts[varmeexpr->GetVstIdx()]++; return; } @@ -42,7 +44,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (dass->GetRHS()->GetMeOp() != kMeOpVar && dass->GetRHS()->GetMeOp() != kMeOpReg) { return; } - ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); + ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); OriginalSt *ost = lhsscalar->GetOst(); if (!ost->IsLocal()) { return; @@ -51,7 +53,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (ty->GetPrimType() == PTY_agg && ty->GetSize() <= 16) { return; } - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (rhsscalar->GetDefBy() != kDefByMustDef) { return; } @@ -247,6 +249,13 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } } bb.SetKind(kBBFallthru); + if (UpdateFreq()) { + int64_t succ0Freq = bb.GetSuccFreq()[0]; + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + } } // A ivar contained in stmt if (stmt2NotNullExpr.find(mestmt) != stmt2NotNullExpr.end()) { @@ -269,8 +278,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // skip fold conditional branch because it may break recorded IfInfo. bool isPme = mirModule.CurFunction()->GetMeFunc()->GetPreMeFunc() != nullptr; - if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch - CondGotoMeStmt *condbr = static_cast(mestmt); + if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch + CondGotoMeStmt *condbr = static_cast(mestmt); + int64_t removedFreq = 0; if (!mirModule.IsJavaModule() && condbr->GetOpnd()->GetMeOp() == kMeOpConst) { CHECK_FATAL(IsPrimitiveInteger(condbr->GetOpnd()->GetPrimType()), "MeHDSE::DseProcess: branch condition must be integer type"); @@ -278,6 +288,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { (condbr->GetOp() == OP_brfalse && !condbr->GetOpnd()->IsZero())) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().back(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -288,6 +301,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // change to unconditional branch BB *succbb = bb.GetSucc().front(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().front(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -297,6 +313,11 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { GotoMeStmt *gotomestmt = irMap.New(condbr->GetOffset()); bb.ReplaceMeStmt(condbr, gotomestmt); } + if (UpdateFreq()) { + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + } } else { DetermineUseCounts(condbr->GetOpnd()); } @@ -305,17 +326,17 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { DetermineUseCounts(mestmt->GetOpnd(i)); } if (mestmt->GetOp() == OP_dassign) { - CheckBackSubsCandidacy(static_cast(mestmt)); + CheckBackSubsCandidacy(static_cast(mestmt)); } } } mestmt = nextstmt; } // update verstUseCOunts for uses in phi operands - for (std::pair phipair : bb.GetMePhiList()) { + for (std::pair phipair : bb.GetMePhiList()) { if (phipair.second->GetIsLive()) { for (ScalarMeExpr *phiOpnd : phipair.second->GetOpnds()) { - VarMeExpr *varx = dynamic_cast(phiOpnd); + VarMeExpr *varx = dynamic_cast(phiOpnd); if (varx) { verstUseCounts[varx->GetVstIdx()]++; } @@ -334,7 +355,7 @@ bool HDSE::NeedNotNullCheck(MeExpr &meExpr, const BB &bb) { if (meExpr.GetOp() == OP_addrof) { return false; } - if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { + if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { return false; } @@ -446,8 +467,7 @@ void HDSE::MarkRegDefByStmt(RegMeExpr ®MeExpr) { MarkPhiRequired(regMeExpr.GetDefPhi()); break; case kDefByChi: { - ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, - "MarkRegDefByStmt: preg cannot be defined by chi"); + ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, "MarkRegDefByStmt: preg cannot be defined by chi"); auto &defChi = regMeExpr.GetDefChi(); MarkChiNodeRequired(defChi); break; @@ -587,8 +607,7 @@ bool HDSE::ExprNonDeletable(const MeExpr &meExpr) const { } case kMeOpVar: { auto &varMeExpr = static_cast(meExpr); - return varMeExpr.IsVolatile() || - (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); + return varMeExpr.IsVolatile() || (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); } case kMeOpIvar: { auto &opIvar = static_cast(meExpr); @@ -618,7 +637,7 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { switch (op) { case OP_dassign: { auto &dasgn = static_cast(meStmt); - VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); + VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); return (varMeExpr != nullptr && varMeExpr->IsVolatile()) || ExprNonDeletable(*dasgn.GetRHS()) || (hdseKeepRef && dasgn.Propagated()) || dasgn.GetWasMayDassign() || (decoupleStatic && varMeExpr != nullptr && varMeExpr->GetOst()->GetMIRSymbol()->IsGlobal()); @@ -632,8 +651,8 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { 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()); + return ivarMeExpr.IsVolatile() || ivarMeExpr.IsFinal() || ExprNonDeletable(*iasgn.GetLHSVal()->GetBase()) || + ExprNonDeletable(*iasgn.GetRHS()); } default: return false; @@ -862,4 +881,4 @@ void HDSE::DoHDSE() { } RemoveNotRequiredStmts(); } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_me/src/me_bb_layout.cpp b/src/mapleall/maple_me/src/me_bb_layout.cpp index 850a013b07..8c5612db86 100644 --- a/src/mapleall/maple_me/src/me_bb_layout.cpp +++ b/src/mapleall/maple_me/src/me_bb_layout.cpp @@ -13,13 +13,14 @@ * See the Mulan PSL v2 for more details. */ #include "me_bb_layout.h" -#include "me_cfg.h" + #include "bb.h" +#include "maple_phase.h" +#include "me_cfg.h" +#include "me_critical_edge.h" #include "me_irmap.h" #include "me_option.h" #include "me_predict.h" -#include "maple_phase.h" -#include "me_critical_edge.h" // This BB layout strategy strictly obeys source ordering when inside try blocks. // This Optimization will reorder the bb layout. it start from the first bb of func. @@ -114,12 +115,10 @@ void BBLayout::BuildChainForLoops() { auto &loops = meLoop->GetMeLoops(); // sort loops from inner most to outer most // need use the same sort rules as prediction? - std::stable_sort(loops.begin(), loops.end(), [](const LoopDesc *loop1, const LoopDesc *loop2) { - return loop1->nestDepth > loop2->nestDepth; - }); + std::stable_sort(loops.begin(), loops.end(), + [](const LoopDesc *loop1, const LoopDesc *loop2) { return loop1->nestDepth > loop2->nestDepth; }); // build chain for loops one by one - auto *context = - layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); + auto *context = layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); for (auto *loop : loops) { BuildChainForLoop(loop, context); } @@ -188,13 +187,13 @@ void BBLayout::DoBuildChain(const BB &header, BBChain &chain, const MapleVector< } bool BBLayout::IsCandidateSucc(const BB &bb, const BB &succ, const MapleVector *context) { - if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) + if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) return false; } - if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains + if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains return false; } - if (succ.GetBBId() == 1) { // special case, exclude common exit BB + if (succ.GetBBId() == 1) { // special case, exclude common exit BB return false; } return true; @@ -240,7 +239,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } uint32 currEdgeFreq = static_cast(bb.GetEdgeFreq(i)); // attention: entryBB->succFreq[i] is always 0 - if (bb.GetBBId() == 0) { // special case for common entry BB + if (bb.GetBBId() == 0) { // special case for common entry BB CHECK_FATAL(bb.GetSucc().size() == 1, "common entry BB should not have more than 1 succ"); bestSucc = succ; break; @@ -253,7 +252,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector if (bestSucc != nullptr) { if (debugChainLayout) { LogInfo::MapleLogger() << "Select [range1 succ ]: "; - LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; + LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; } return bestSucc; } @@ -267,12 +266,12 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } bool useBBFreq = false; - if (useBBFreq) { // use bb freq + if (useBBFreq) { // use bb freq if (header->GetFrequency() > bestFreq) { // find max bb freq bestFreq = header->GetFrequency(); bestSucc = header; } - } else { // use edge freq + } else { // use edge freq uint32 subBestFreq = 0; for (auto *pred : header->GetPred()) { uint32 curFreq = static_cast(pred->GetEdgeFreq(header)); @@ -595,8 +594,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { // condgoto's succ layout: [0] fallthru succ, [1] target succ, [2-...] eh succ/wontexit succ // goto's succ layout: [0] target succ, [1-...] eh succ/wontexit succ BB *brTargetBB = bb.GetKind() == kBBCondGoto ? bb.GetSucc(1) : bb.GetSucc(0); - CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), - "target is same as fallthru"); + CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), "target is same as fallthru"); if (brTargetBB->GetAttributes(kBBAttrWontExit)) { return; } @@ -608,8 +606,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { bbVisited[bb.GetBBId().GetIdx()] = true; OptimizeBranchTarget(*brTargetBB); // optimize stmt - BB *newTargetBB = - (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); + BB *newTargetBB = (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); if (newTargetBB == brTargetBB) { return; } @@ -682,7 +679,7 @@ void BBLayout::AddBB(BB &bb) { // If the pred bb is goto bb and the target bb of goto bb is the current bb which is be added to layoutBBs, change the // goto bb to fallthru bb. if (layoutBBs.size() > 1) { - BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. + BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. if (predBB->GetKind() != kBBGoto) { return; } @@ -880,7 +877,6 @@ void BBLayout::RemoveUnreachable(BB &bb) { } } - void BBLayout::UpdateNewBBWithAttrTry(const BB &bb, BB &fallthru) const { auto tryBB = &bb; fallthru.SetAttributes(kBBAttrIsTry); @@ -945,6 +941,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { index--; fallthru.AddPred(*newFallthru, index); newFallthru->SetFrequency(fallthru.GetFrequency()); + if (cfg->UpdateCFGFreq()) { + newFallthru->PushBackSuccFreq(fallthru.GetFrequency()); + } if (enabledDebug) { LogInfo::MapleLogger() << "Created fallthru and goto original fallthru" << '\n'; } @@ -954,7 +953,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { } void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { - if (needDealWithTryBB) { return; } + if (needDealWithTryBB) { + return; + } auto *fallthru = bb.GetSucc().front(); while (fallthru && (fallthru->GetPred().size() == 1) && (BBEmptyAndFallthru(*fallthru) || BBContainsOnlyGoto(*fallthru)) && @@ -964,7 +965,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { bb.ReplaceSucc(fallthru, newFallthru); ASSERT(fallthru->GetPred().empty(), "fallthru should not has other pred"); ChangeToFallthruFromCondGoto(bb); - bb.GetSucc().resize(1); // resize succ to 1 + bb.GetSucc().resize(1); // resize succ to 1 } else if (newFallthru->GetPred().size() == 1) { if (newFallthru->GetBBLabel() != 0) { // reset newFallthru label @@ -982,7 +983,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { } void BBLayout::DumpBBPhyOrder() const { - LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; + LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; for (auto bb : layoutBBs) { LogInfo::MapleLogger() << bb->GetBBId(); if (bb != layoutBBs.back()) { @@ -1059,8 +1060,7 @@ void BBLayout::LayoutWithoutProf() { } ASSERT(!(isTry && GetTryOutstanding()), "cannot emit another try if last try has not been ended"); if (nextBB->GetAttributes(kBBAttrIsTryEnd)) { - ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || - IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), + ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), "cannot emit endtry bb before its corresponding try bb"); } } @@ -1204,8 +1204,8 @@ void BBLayout::BuildEdges() { allEdges.emplace_back(layoutAlloc.GetMemPool()->New(bb, dest, w)); } } - std::stable_sort(allEdges.begin(), allEdges.end(), [](const BBEdge *edge1, const BBEdge *edge2) { - return edge1->GetWeight() > edge2->GetWeight(); }); + std::stable_sort(allEdges.begin(), allEdges.end(), + [](const BBEdge *edge1, const BBEdge *edge2) { return edge1->GetWeight() > edge2->GetWeight(); }); } BB *BBLayout::GetBBFromEdges() { @@ -1214,8 +1214,8 @@ BB *BBLayout::GetBBFromEdges() { BB *srcBB = edge->GetSrcBB(); BB *destBB = edge->GetDestBB(); if (enabledDebug) { - LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " - << srcBB->GetEdgeFreq(destBB) << '\n'; + LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " << srcBB->GetEdgeFreq(destBB) + << '\n'; } if (!laidOut[srcBB->GetBBId()]) { @@ -1252,7 +1252,7 @@ BB *BBLayout::NextBBProf(BB &bb) { return NextBBProf(*succBB); } // max freq intial - uint64 maxFreq = 0; + uint64 maxFreq = 0; size_t idx = 0; bool found = false; for (size_t i = 0; i < bb.GetSucc().size(); ++i) { @@ -1282,11 +1282,14 @@ void BBLayout::RebuildFreq() { auto *hook = phase->GetAnalysisInfoHook(); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MEDominance::id); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MELoopAnalysis::id); - dom = static_cast( - hook->ForceRunAnalysisPhase>(&MEDominance::id, func))->GetResult(); + dom = static_cast(hook->ForceRunAnalysisPhase>(&MEDominance::id, func)) + ->GetResult(); meLoop = static_cast( - hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func))->GetResult(); - MePrediction::RebuildFreq(func, *dom, *meLoop); + hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func)) + ->GetResult(); + if (!cfg->UpdateCFGFreq()) { + MePrediction::RebuildFreq(func, *dom, *meLoop); + } } void BBLayout::LayoutWithProf(bool useChainLayout) { @@ -1346,8 +1349,7 @@ void BBLayout::VerifyBB() { if (bb->GetKind() == kBBCondGoto) { auto *fallthru = bb->GetSucc(0); auto *targetBB = bb->GetSucc(1); - if (fallthru == targetBB || - (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { + if (fallthru == targetBB || (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { LogInfo::MapleLogger() << "WARN: cond BB " << bb->GetBBId() << " has same target"; } } @@ -1375,11 +1377,15 @@ bool MEBBLayout::PhaseRun(maple::MeFunction &f) { bbLayout->RunLayout(); f.SetLaidOutBBs(bbLayout->GetBBs()); - if (DEBUGFUNC_NEWPM(f)) { + if (DEBUGFUNC_NEWPM(f) || Options::profileUse) { // verify CFG : check condBB's succs should be different bbLayout->VerifyBB(); bbLayout->DumpBBPhyOrder(); - cfg->DumpToFile("afterBBLayout", false); + if (cfg->UpdateCFGFreq() && cfg->DumpIRProfileFile()) { + cfg->DumpToFile("after-bblayout", false, true); + } else { + cfg->DumpToFile("afterBBLayout", false); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index d5458c7769..3b9a752fde 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -13,30 +13,33 @@ * See the Mulan PSL v2 for more details. */ #include "me_cfg.h" -#include + #include +#include #include + #include "bb.h" -#include "ssa_mir_nodes.h" -#include "me_irmap.h" -#include "mir_builder.h" #include "me_critical_edge.h" +#include "me_irmap.h" #include "me_loop_canon.h" +#include "mir_builder.h" #include "mir_lower.h" +#include "ssa_mir_nodes.h" namespace { constexpr int kFuncNameLenLimit = 80; } namespace maple { -#define MATCH_STMT(stmt, kOpCode) do { \ - while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ - (stmt) = (stmt)->GetNext(); \ - } \ - if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ - return false; \ - } \ -} while (0) // END define +#define MATCH_STMT(stmt, kOpCode) \ + do { \ + while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ + (stmt) = (stmt)->GetNext(); \ + } \ + if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ + return false; \ + } \ + } while (0) // END define // determine if need to be replaced by assertnonnull bool MeCFG::IfReplaceWithAssertNonNull(const BB &bb) const { const StmtNode *stmt = bb.GetStmtNodes().begin().d(); @@ -308,7 +311,7 @@ bool MeCFG::FindUse(const StmtNode &stmt, StIdx stIdx) const { return FindExprUse(*iNode.GetRHS(), stIdx); } } - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_eval: case OP_free: case OP_switch: { @@ -511,7 +514,6 @@ void MeCFG::FixMirCFG() { } } - // replace "if() throw NPE()" with assertnonnull void MeCFG::ReplaceWithAssertnonnull() { constexpr char rnnTypeName[] = @@ -681,7 +683,7 @@ void MeCFG::ConvertPhiList2IdentityAssigns(BB &meBB) const { DassignNode *dassign = func.GetMIRModule().GetMIRBuilder()->CreateStmtDassign(*st, 0, dread2); func.GetMeSSATab()->GetStmtsSSAPart().SetSSAPartOf( *dassign, func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartMp()->New( - &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); + &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); auto *theSSAPart = static_cast(func.GetMeSSATab()->GetStmtsSSAPart().SSAPartOf(*dassign)); theSSAPart->SetSSAVar(*((*phiIt).second.GetResult())); @@ -700,15 +702,15 @@ void MeCFG::ConvertMePhiList2IdentityAssigns(BB &meBB) const { CHECK_FATAL(ost, "ost is nullptr!"); if (ost->IsSymbolOst() && ost->GetIndirectLev() == 0) { MePhiNode *varPhi = phiIt->second; - auto *dassign = func.GetIRMap()->NewInPool( - static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); + auto *dassign = + func.GetIRMap()->NewInPool(static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); dassign->SetBB(varPhi->GetDefBB()); dassign->SetIsLive(varPhi->GetIsLive()); meBB.PrependMeStmt(dassign); } else if (ost->IsPregOst()) { MePhiNode *regPhi = phiIt->second; - auto *regAss = func.GetIRMap()->New( - OP_regassign, static_cast(regPhi->GetLHS()), regPhi->GetOpnd(0)); + auto *regAss = func.GetIRMap()->New(OP_regassign, static_cast(regPhi->GetLHS()), + regPhi->GetOpnd(0)); regPhi->GetLHS()->SetDefByStmt(*regAss); regPhi->GetLHS()->SetDefBy(kDefByStmt); regAss->SetBB(regPhi->GetDefBB()); @@ -779,6 +781,10 @@ void MeCFG::WontExitAnalysis() { newBB->SetKindReturn(); newBB->SetAttributes(kBBAttrArtificial); bb->AddSucc(*newBB); + // newBB is added as succ of bb, set freq 0 as its edge frequency + if (updateFreq) { + bb->PushBackSuccFreq(0); + } GetCommonExitBB()->AddExit(*newBB); bb->FindWillExitBBs(currVisitedBBs); // Mark other bbs in the loop as visited. } @@ -835,15 +841,13 @@ void MeCFG::VerifyLabels() const { if (stmtNodes.back().GetOpCode() == OP_throw) { continue; } - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in goto"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in goto"); } else if (mirBB->GetKind() == kBBCondGoto) { - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in conditional branch"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in conditional branch"); } else if (mirBB->GetKind() == kBBSwitch) { auto &switchStmt = static_cast(stmtNodes.back()); LabelIdx targetLabIdx = switchStmt.GetDefaultLabel(); @@ -966,7 +970,7 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge return; } std::ofstream cfgFile; - std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer + std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer std::streambuf *buf = cfgFile.rdbuf(); LogInfo::MapleLogger().rdbuf(buf); const std::string &fileName = ConstructFileNameToDump(prefix); @@ -980,7 +984,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge if (bIt == common_exit()) { // specical case for common_exit_bb for (auto it = bb->GetPred().begin(); it != bb->GetPred().end(); ++it) { - cfgFile << "BB" << (*it)->GetBBId()<< " -> " << "BB" << bb->GetBBId() << "[style=dotted];\n"; + cfgFile << "BB" << (*it)->GetBBId() << " -> " + << "BB" << bb->GetBBId() << "[style=dotted];\n"; } continue; } @@ -989,7 +994,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } for (auto it = bb->GetSucc().begin(); it != bb->GetSucc().end(); ++it) { - cfgFile << "BB" << bb->GetBBId() << " -> " << "BB" << (*it)->GetBBId(); + cfgFile << "BB" << bb->GetBBId() << " -> " + << "BB" << (*it)->GetBBId(); if (bb == GetCommonEntryBB()) { cfgFile << "[style=dotted]"; continue; @@ -1013,20 +1019,19 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } } if (laidOut != nullptr) { - static std::vector colors = { - "indianred1", "darkorange1", "lightyellow1", "green3", "cyan", "dodgerblue2", "purple2" - }; + static std::vector colors = {"indianred1", "darkorange1", "lightyellow1", "green3", + "cyan", "dodgerblue2", "purple2"}; uint32 colorIdx = 0; size_t clusterSize = laidOut->size() / colors.size(); uint32 cnt = 0; for (uint32 i = 0; i < laidOut->size(); ++i) { auto *bb = (*laidOut)[i]; auto bbId = bb->GetBBId(); - std::string bbNameLabel = dumpEdgeFreq ? - "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) : - "BB" + std::to_string(bbId.GetIdx()); - cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] << ", label=" << - bbNameLabel << "__" << i << "]\n"; + std::string bbNameLabel = + dumpEdgeFreq ? "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) + : "BB" + std::to_string(bbId.GetIdx()); + cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] + << ", label=" << bbNameLabel << "__" << i << "]\n"; ++cnt; if (cnt > clusterSize) { cnt = 0; @@ -1147,8 +1152,8 @@ bool MeCFG::UnifyRetBBs() { if (func.GetMirFunc()->IsReturnVoid()) { newRetBB->SetFirst(mirBuilder->CreateStmtReturn(nullptr)); } else { - unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", - kStVar, kScAuto, func.GetMirFunc(), kScopeLocal); + unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", kStVar, kScAuto, + func.GetMirFunc(), kScopeLocal); newRetBB->SetFirst(mirBuilder->CreateStmtReturn(mirBuilder->CreateExprDread(*unifiedFuncRet))); } newRetBB->SetLast(newRetBB->GetStmtNodes().begin().d()); @@ -1364,8 +1369,8 @@ void MeCFG::CreateBasicBlocks() { } break; } - // fall thru to handle as return - [[clang::fallthrough]]; + // fall thru to handle as return + [[clang::fallthrough]]; case OP_gosub: case OP_retsub: case OP_return: { @@ -1397,7 +1402,7 @@ void MeCFG::CreateBasicBlocks() { if (!curBB->IsEmpty()) { StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1430,7 +1435,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1461,7 +1466,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1592,7 +1597,7 @@ void MeCFG::CreateBasicBlocks() { } } } while (nextStmt != nullptr); - ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping + ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping ASSERT(lastTryBB == nullptr, "unclosed tryBB"); // tryandendtry should be one-one mapping auto *lastBB = curBB; if (lastBB->IsEmpty()) { @@ -1622,8 +1627,7 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { if (succ == nullptr) { continue; } - if (inQueue.find(succ) != inQueue.end() || - std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { + if (inQueue.find(succ) != inQueue.end() || std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { continue; } bool predAllVisited = true; @@ -1651,8 +1655,8 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { } void MeCFG::BuildSCCDFS(BB &bb, uint32 &visitIndex, std::vector &sccNodes, - std::vector &visitedOrder, std::vector &lowestOrder, - std::vector &inStack, std::stack &visitStack) { + std::vector &visitedOrder, std::vector &lowestOrder, std::vector &inStack, + std::stack &visitStack) { uint32 id = bb.UintID(); visitedOrder[id] = visitIndex; lowestOrder[id] = visitIndex; @@ -1780,7 +1784,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M } } else if (currBB.GetKind() == kBBCondGoto) { if (currBB.GetSucc(0) == &newTarget) { - return; // no need to update offset for fallthru BB + return; // no need to update offset for fallthru BB } BB *gotoBB = currBB.GetSucc().at(1); ASSERT(gotoBB == &newTarget, "[FUNC: %s]newTarget is not one of CondGoto's succ BB", func.GetName().c_str()); @@ -1818,7 +1822,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M switchStmt.SetDefaultLabel(label); } for (size_t i = 0; i < switchStmt.GetSwitchTable().size(); ++i) { - LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; + LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; if (caseLabel == oldLabelIdx) { switchStmt.UpdateCaseLabelAt(i, label); } @@ -1875,7 +1879,7 @@ void MeCFG::ConstructEdgeFreqFromBBFreq() { // set bb frequency from stmt record void MeCFG::ConstructBBFreqFromStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1885,13 +1889,14 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { auto eIt = valid_end(); for (auto bIt = valid_begin(); bIt != eIt; ++bIt) { if ((*bIt)->IsEmpty()) continue; - StmtNode& first = (*bIt)->GetFirst(); + StmtNode &first = (*bIt)->GetFirst(); if (funcData->stmtFreqs.count(first.GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[first.GetStmtID()]); } else if (funcData->stmtFreqs.count((*bIt)->GetLast().GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[(*bIt)->GetLast().GetStmtID()]); } else { - LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" << "\n"; + LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" + << "\n"; ASSERT(0, "no freq set"); } } @@ -1912,10 +1917,13 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { ConstructEdgeFreqFromBBFreq(); // clear stmtFreqs since cfg frequency is create funcData->stmtFreqs.clear(); + + // set updateFrequency with true + updateFreq = true; } void MeCFG::ConstructStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1926,13 +1934,12 @@ void MeCFG::ConstructStmtFreq() { auto *bb = *bIt; if (bIt == common_entry()) { funcData->entryFreq = bb->GetFrequency(); - funcData->real_entryfreq = funcData->entryFreq; + funcData->realEntryfreq = funcData->entryFreq; } for (auto &stmt : bb->GetStmtNodes()) { Opcode op = stmt.GetOpCode(); // record bb start/end stmt - if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || - stmt.GetStmtID() == bb->GetLast().GetStmtID() || + if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || stmt.GetStmtID() == bb->GetLast().GetStmtID() || IsCallAssigned(op) || op == OP_call) { funcData->stmtFreqs[stmt.GetStmtID()] = bb->GetFrequency(); } @@ -1942,39 +1949,105 @@ void MeCFG::ConstructStmtFreq() { // bb frequency may be changed in transform phase, // update edgeFreq with new BB frequency by scale -void MeCFG::UpdateEdgeFreqWithNewBBFreq() { - for (size_t idx = 0; idx < bbVec.size(); ++idx) { - BB *currBB = bbVec[idx]; - if (currBB == nullptr || currBB->GetSucc().empty()) { +void MeCFG::UpdateEdgeFreqWithBBFreq() { + BuildSCC(); + for (size_t i = 0; i < GetSccTopologicalVec().size(); ++i) { + SCCOfBBs *scc = GetSccTopologicalVec()[i]; + CHECK_FATAL(scc != nullptr, "scc must not be null"); + if (scc->GetBBs().size() > 1) { + BBTopologicalSort(*scc); + } + const uint32 maxLoopCount = 2; + unsigned loopCount = scc->GetBBs().size() > 1 ? maxLoopCount : 1; + for (unsigned j = 0; j < loopCount; ++j) { + for (BB *bb : scc->GetBBs()) { + if (bb == nullptr) { + continue; + } + // collect pred total except entry + if (!bb->GetAttributes(kBBAttrIsEntry)) { + int64_t inputFreq = 0; + for (auto *pred : bb->GetPred()) { + int idx = pred->GetSuccIndex(*bb); + ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); + inputFreq += pred->GetSuccFreq()[idx]; + } + bb->SetFrequency(inputFreq); + } + // make bb frequency and succs frequency consistent + bb->UpdateEdgeFreqs(false); + } + } + } +} + +void MeCFG::ClearFuncFreqInfo() { + SetUpdateCFGFreq(false); + func.GetMirFunc()->SetFuncProfData(nullptr); + auto &bbVec = GetAllBBs(); + for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit + auto *bb = bbVec[i]; + if (bb == nullptr) { continue; } - // make bb frequency and succs frequency consistent - currBB->UpdateEdgeFreqs(); + bb->SetFrequency(0); + bb->GetSuccFreq().clear(); } } -void MeCFG::VerifyBBFreq() { +// return value is 0 means pass verification, else has problem +int MeCFG::VerifyBBFreq(bool checkFatal) { + int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + ASSERT(entryFreq >= 0, "sanity check"); + bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit auto *bb = bbVec[i]; if (bb == nullptr || bb->GetAttributes(kBBAttrIsEntry) || bb->GetAttributes(kBBAttrIsExit)) { continue; } - // wontexit bb may has wrong succ, skip it + // check case 1: entry count is zero, internal bb has frequency value > 0 + if (entryIsZero && bb->GetFrequency() > 0) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: function entryFreq is zero but internal bb frequency > 0"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } + // check case 2: bb succ frequence numbers should be equal to succ number except wontexit bb + // may has wrong succ, skip it if (bb->GetSuccFreq().size() != bb->GetSucc().size() && !bb->GetAttributes(kBBAttrWontExit)) { - CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + } else { + ClearFuncFreqInfo(); + return 1; + } } - // bb freq == sum(out edge freq) + // check case 3: bb freq == sum(out edge freq) uint64 succSumFreq = 0; for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } if (succSumFreq != bb->GetFrequency()) { - LogInfo::MapleLogger() << "[VerifyFreq failure] BB" << bb->GetBBId() << " freq: " << - bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq << std::endl; - LogInfo::MapleLogger() << func.GetName() << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + int diff = succSumFreq - bb->GetFrequency(); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } } } + return 0; } bool MEMeCfg::PhaseRun(MeFunction &f) { @@ -2008,31 +2081,33 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (!f.GetMIRModule().IsJavaModule() && MeOption::unifyRets) { theCFG->UnifyRetBBs(); } + theCFG->Verify(); // construct bb freq from stmt freq if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { theCFG->ConstructBBFreqFromStmtFreq(); + if (theCFG->DumpIRProfileFile()) { + std::string fileName = "after-mecfgbuild"; + if (f.IsPme()) { + fileName.append("-lfo"); + } else { + fileName.append("-mplme"); + } + theCFG->DumpToFile(fileName, false, true); + } } - theCFG->Verify(); return false; } bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + // if transform pass is not fully support, set disableFreqInfo to true + // function profile information will be deleted after verification phase + bool disableFreqInfo = false; + if (f.GetCfg()->UpdateCFGFreq()) { f.GetCfg()->VerifyBBFreq(); } - // hack code here: no use profile data after verifycation pass since - // following tranform phases related of cfg change are not touched - f.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = f.GetCfg()->GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; - if (bb == nullptr) { - continue; - } - bb->SetFrequency(0); - bb->GetSuccFreq().clear(); - } - + if (!disableFreqInfo) return false; + // clear function profile information + f.GetCfg()->ClearFuncFreqInfo(); return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_critical_edge.cpp b/src/mapleall/maple_me/src/me_critical_edge.cpp index e47078d693..4dca8f82a2 100644 --- a/src/mapleall/maple_me/src/me_critical_edge.cpp +++ b/src/mapleall/maple_me/src/me_critical_edge.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_critical_edge.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" #include "me_function.h" -#include "me_loop_analysis.h" #include "me_irmap.h" +#include "me_loop_analysis.h" +#include "me_option.h" // This phase finds critical edges and split them into two, because their // presence would restrict the optimizations performed by SSAPRE-based phases. @@ -98,8 +100,8 @@ void MeSplitCEdge::UpdateCaseLabel(BB &newBB, MeFunction &func, BB &pred, BB &su } } -void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, - BB &succ, BB *&newBB, bool &isInsertAfterPred) const { +void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, BB &succ, BB *&newBB, + bool &isInsertAfterPred) const { if ((!succ.GetStmtNodes().empty() && succ.GetStmtNodes().front().GetOpCode() == OP_try) || (!succ.IsMeStmtEmpty() && succ.GetFirstMe()->GetOp() == OP_try)) { newBB = &func.GetCfg()->InsertNewBasicBlock(pred, false); @@ -117,8 +119,8 @@ void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const { if (isDebugFunc) { - LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << - succ.GetBBId() << "\n"; + LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << succ.GetBBId() + << "\n"; pred.Dump(&func.GetMIRModule()); succ.Dump(&func.GetMIRModule()); } @@ -160,8 +162,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const newBB->SetAttributes(kBBAttrArtificial); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData() && - (!(func.IsPme() || func.IsLfo()))) { + if (cfg->UpdateCFGFreq() && (!(func.IsPme() || func.IsLfo()))) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -189,8 +190,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const } // profileGen invokes MESplitCEdge to remove critical edges without going through ME completely // newBB needs to be materialized - if (Options::profileGen || - (Options::profileUse && (func.IsPme() || func.IsLfo()))) { + if (Options::profileGen || (Options::profileUse && (func.IsPme() || func.IsLfo()))) { LabelIdx succLabel = succ.GetBBLabel(); ASSERT(succLabel != 0, "succ's label missed"); if (func.GetIRMap() != nullptr) { @@ -306,7 +306,7 @@ bool MESplitCEdge::PhaseRun(maple::MeFunction &f) { mscedge.SplitCriticalEdgeForMeFunc(f); if (Options::profileUse) { if ((f.IsPme() || f.IsLfo()) && f.GetPreMeFunc()) { - // new inserted BB will break while/if label information and IR layout + // new inserted BB break cached while/if label information and IR layout f.GetPreMeFunc()->label2IfInfo.clear(); f.GetPreMeFunc()->label2WhileInfo.clear(); f.GetPreMeFunc()->pmeCreatedIfLabelSet.clear(); diff --git a/src/mapleall/maple_me/src/me_dse.cpp b/src/mapleall/maple_me/src/me_dse.cpp index c2ad027a7e..2d393a9ada 100644 --- a/src/mapleall/maple_me/src/me_dse.cpp +++ b/src/mapleall/maple_me/src/me_dse.cpp @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "me_dse.h" + #include namespace maple { @@ -33,7 +34,7 @@ void MeDSE::VerifyPhi() const { const OriginalSt *ost = func.GetMeSSATab()->GetOriginalStFromID(pair.first); CHECK_FATAL(ost, "ost is nullptr!"); CHECK_FATAL(!ost->IsSymbolOst() || ost->GetIndirectLev() != 0, - "phi is live and non-virtual in bb with zero or one pred"); + "phi is live and non-virtual in bb with zero or one pred"); } else if (pair.second.GetPhiOpnds().size() != predBBNums) { ASSERT(false, "phi opnd num is not consistent with pred bb num(need update phi)"); } @@ -71,8 +72,11 @@ bool MEDse::PhaseRun(maple::MeFunction &f) { f.Verify(); // cfg change , invalid results in MeFuncResultMgr if (dse.UpdatedCfg()) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { - f.GetCfg()->UpdateEdgeFreqWithNewBBFreq(); + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile(("after-dse" + std::to_string(f.dseRuns)), false, true); + } } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); } diff --git a/src/mapleall/maple_me/src/me_hdse.cpp b/src/mapleall/maple_me/src/me_hdse.cpp index 6283697dd9..9cc7fa1907 100644 --- a/src/mapleall/maple_me/src/me_hdse.cpp +++ b/src/mapleall/maple_me/src/me_hdse.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_hdse.h" + #include + +#include "hdse.h" +#include "me_ssa.h" #include "ssa_mir_nodes.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "hdse.h" // The hdse phase performs dead store elimination using the well-known algorithm // based on SSA. The algorithm works as follows: @@ -55,7 +57,7 @@ void MeHDSE::ProcessWhileInfos() { if (preMeFunc == nullptr) { return; } - MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); + MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); for (; it != preMeFunc->label2WhileInfo.end(); ++it) { if (it->second->initExpr != nullptr && (it->second->initExpr->GetMeOp() == maple::kMeOpVar || it->second->initExpr->GetMeOp() == maple::kMeOpReg)) { @@ -66,7 +68,7 @@ void MeHDSE::ProcessWhileInfos() { void MeHDSE::BackwardSubstitution() { for (DassignMeStmt *dass : backSubsCands) { - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (verstUseCounts[rhsscalar->GetVstIdx()] != 1) { continue; } @@ -110,9 +112,8 @@ void MakeEmptyTrysUnreachable(MeFunction &func) { } BB *endTry = *endTryIt; auto &meStmts = tryBB->GetMeStmts(); - if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && - meStmts.front().GetOp() == OP_try && tryBB->GetMePhiList().empty() && - endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { + if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && meStmts.front().GetOp() == OP_try && + tryBB->GetMePhiList().empty() && endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { // we found a try BB followed by an empty endtry BB BB *targetBB = endTry->GetSucc(0); while (!tryBB->GetPred().empty()) { @@ -190,6 +191,7 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MeHDSE hdse = MeHDSE(f, *dom, *hMap, aliasClass, DEBUGFUNC_NEWPM(f)); hdse.hdseKeepRef = MeOption::dseKeepRef; + hdse.SetUpdateFreq(Options::profileUse && f.GetMirFunc()->GetFuncProfData()); if (f.hdseRuns > 2) { hdse.SetRemoveRedefine(true); } @@ -198,6 +200,13 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MakeEmptyTrysUnreachable(f); (void)f.GetCfg()->UnreachCodeAnalysis(true); f.GetCfg()->WontExitAnalysis(); + // update frequency + if (hdse.UpdateFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-HDSE" + std::to_string(f.hdseRuns), false, true); + } + } if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "\n============== HDSE =============" << '\n'; f.Dump(false); diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 951da51ee7..05c4b15f8e 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_canon.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -39,8 +41,7 @@ void MeLoopCanon::FindHeadBBs(Dominance &dom, const BB *bb, std::mapGetBBLabel() != 0) { - const MapleUnorderedSet &addrTakenLabels = - func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); + const MapleUnorderedSet &addrTakenLabels = func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); if (addrTakenLabels.find(bb->GetBBLabel()) != addrTakenLabels.end()) { hasIgoto = true; } @@ -71,8 +72,7 @@ void MeLoopCanon::UpdateTheOffsetOfStmtWhenTargetBBIsChange(BB &curBB, const BB static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); - } else if (lastStmt.GetOp() == OP_goto && - static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { + } else if (lastStmt.GetOp() == OP_goto && static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); } else if (lastStmt.GetOp() == OP_switch) { @@ -96,8 +96,19 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, // quick split auto *pred = splitList[0]; auto index = pred->GetSuccIndex(*splittedBB); + // add frequency to mergedBB + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + uint64_t freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(freq); + mergedBB->PushBackSuccFreq(freq); + } splittedBB->ReplacePred(pred, mergedBB); pred->AddSucc(*mergedBB, static_cast(static_cast(index))); + if (updateFreqs) { + pred->AddSuccFreq(mergedBB->GetFrequency(), static_cast(static_cast(index))); + } if (!pred->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*pred, *splittedBB, *mergedBB); } @@ -112,6 +123,7 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, mergedBB->GetMePhiList().emplace(latchLhs->GetOstIdx(), latchPhi); phiIter.second->GetOpnds().push_back(latchLhs); } + uint64_t freq = 0; for (BB *pred : splitList) { auto pos = splittedBB->GetPredIndex(*pred); for (auto &phiIter : mergedBB->GetMePhiList()) { @@ -119,7 +131,17 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, phiIter.second->GetOpnds().push_back(splittedBB->GetMePhiList().at(phiIter.first)->GetOpnd(pos)); } splittedBB->RemovePhiOpnd(pos); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + } pred->ReplaceSucc(splittedBB, mergedBB); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*mergedBB); + pred->SetSuccFreq(idx, freq); + } if (pred->GetMeStmts().empty()) { continue; } @@ -141,6 +163,9 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, } } splittedBB->AddPred(*mergedBB); + if (updateFreqs) { + mergedBB->PushBackSuccFreq(mergedBB->GetFrequency()); + } isCFGChange = true; } @@ -151,16 +176,14 @@ void MeLoopCanon::Merge(const std::map> &heads) { BB *head = cfg->GetBBFromID(iter->first); // skip case : check latch bb is already added // one pred is preheader bb and the other is latch bb - if ((head->GetPred().size() == 2) && - (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && - (head->GetPred(0)->GetKind() == kBBFallthru) && - (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && + if ((head->GetPred().size() == 2) && (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && + (head->GetPred(0)->GetKind() == kBBFallthru) && (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && (head->GetPred(1)->GetKind() == kBBFallthru)) { continue; } auto *latchBB = cfg->NewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop latchBB->SetKind(kBBFallthru); SplitPreds(iter->second, head, latchBB); } @@ -244,8 +267,17 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { BB *newExitBB = cfg->NewBasicBlock(); newExitBB->SetKind(kBBFallthru); auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + freq = curBB->GetSuccFreq()[idx]; + } curBB->ReplaceSucc(succ, newExitBB); succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(freq); + newExitBB->PushBackSuccFreq(freq); + } if (!curBB->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } @@ -299,7 +331,8 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { auto *dom = GET_ANALYSIS(MEDominance, f); ASSERT(dom != nullptr, "dom is null in MeDoLoopCanon::Run"); MemPool *loopCanonMp = GetPhaseMemPool(); - auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f)); + bool updateFrequency = (Options::profileUse && f.GetMirFunc()->GetFuncProfData()); + auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f), updateFrequency); // 1. Add preheaderBB and normalization headBB for loop. meLoopCanon->NormalizationHeadAndPreHeaderOfLoop(*dom); @@ -316,6 +349,9 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { meLoopCanon->NormalizationExitOfLoop(*meLoop); if (meLoopCanon->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); + if (updateFrequency && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopcanon", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index 23a572736d..d3f9505fed 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_inversion.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -121,8 +123,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is in loopbody, latchBB need convert condgoto and make original target as its fallthru bool swapSuccOfLatch = (swapSuccs.find(std::make_pair(&bb, &pred)) != swapSuccs.end()); if (isDebugFunc) { - LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " - << pred.GetBBId(); + LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " << pred.GetBBId(); if (swapSuccOfLatch) { LogInfo::MapleLogger() << " need swap succs\n"; } else { @@ -132,9 +133,9 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapNewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop // update newBB frequency : copy predBB succFreq as latch frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { + if (func.GetCfg()->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(bb); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -144,7 +145,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapSetKind(bb.GetKind()); // update succFreq - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { - int succFreqSize = bb.GetSuccFreq().size(); - ASSERT(latchBB->GetSucc().size() == succFreqSize, "sanity check"); - // copy bb succFreq as latch frequency - for (int i = 0; i < succFreqSize; i++) { - latchBB->PushBackSuccFreq(bb.GetSuccFreq()[i]); - } - if (bb.GetFrequency() > 0) { - // swap frequency and fixed the frequency value - if (swapSuccOfLatch) { - ASSERT(latchBB->GetKind() == kBBCondGoto, "impossible"); - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[1] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newtgFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBCondGoto) { - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[0] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); // freq to exit BB - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - // update bb succ frequency - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newftFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { - int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; - latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format - bb.SetSuccFreq(0, bb.GetFrequency()); + if (func.GetCfg()->UpdateCFGFreq()) { + if (latchBB->GetKind() == kBBCondGoto) { + BB *succInloop = swapSuccOfLatch ? bb.GetSucc(0) : bb.GetSucc(1); + if ((latchBB->GetFrequency() != 0) && (succInloop->GetFrequency() > 0)) { + // loop is executed + int64_t latchFreq = latchBB->GetFrequency(); + if (swapSuccOfLatch) { + // bb fallthru is in loop, frequency of bb -> exitbb is set 0 + // latchBB fallthru is loop exit + int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { // assume loop body executed only once + bb.SetSuccFreq(0, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(1, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + latchBB->PushBackSuccFreq(0); + } + } else { + // bb->fallthru is loop exit, edge frequency of bb ->exitbb is set 0 + // latchBB fallthru is in loop + int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(1, bb.GetFrequency()); + bb.SetSuccFreq(0, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { + bb.SetSuccFreq(1, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(0, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + } + } } else { - ASSERT(0, "NYI:: unexpected bb type"); + // loop is not executed + if (latchBB->GetFrequency() != 0) { + if (swapSuccOfLatch) { + bb.SetSuccFreq(0, 0); + bb.SetSuccFreq(1, bb.GetFrequency()); + } else { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + } + } + ASSERT(latchBB->GetFrequency() == 0, "sanity check"); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(0); } + } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { + int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; + latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format + bb.SetSuccFreq(0, bb.GetFrequency()); + } else { + ASSERT(0, "NYI:: unexpected bb type"); } } // swap latchBB's succ if needed @@ -332,8 +355,8 @@ void MeLoopInversion::ExecuteLoopInversion(MeFunction &func, Dominance &dom) { } if ((NeedConvert(&func, *succ, *tmpPred, localAlloc, swapSuccs))) { if (isDebugFunc) { - LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() - << " <-- " << tmpPred->GetBBId() << '\n'; + LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() << " <-- " << tmpPred->GetBBId() + << '\n'; } backEdges.push_back(std::make_pair(succ, tmpPred)); } @@ -362,6 +385,9 @@ bool MELoopInversion::PhaseRun(maple::MeFunction &f) { if (meLoopInversion->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopinversion", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_unrolling.cpp b/src/mapleall/maple_me/src/me_loop_unrolling.cpp index e398584e28..98a5429af0 100644 --- a/src/mapleall/maple_me/src/me_loop_unrolling.cpp +++ b/src/mapleall/maple_me/src/me_loop_unrolling.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_unrolling.h" -#include + #include +#include + #include "me_cfg.h" #include "me_option.h" -#include "mir_module.h" -#include "mir_builder.h" #include "me_phase_manager.h" +#include "mir_builder.h" +#include "mir_module.h" namespace maple { bool LoopUnrollingExecutor::enableDebug = false; @@ -36,13 +38,15 @@ bool ProfileCheck(const maple::MeFunction &f) { auto &profile = f.GetMIRModule().GetProfile(); if (!profile.IsValid()) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" << "\n"; + LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" + << "\n"; } return false; } if (!profile.CheckFuncHot(f.GetName())) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "func is not hot" << "\n"; + LogInfo::MapleLogger() << "func is not hot" + << "\n"; } return false; } @@ -69,12 +73,12 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { case OP_brfalse: case OP_brtrue: case OP_maydassign: - CASE_OP_ASSERT_BOUNDARY { - cost += kTwoInsn; - break; - } + CASE_OP_ASSERT_BOUNDARY { + cost += kTwoInsn; + break; + } case OP_iassign: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_membaracquire: { cost += kThreeInsn; break; @@ -99,7 +103,7 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { } default: if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "consider this op :"<< meStmt.GetOp() << "\n"; + LogInfo::MapleLogger() << "consider this op :" << meStmt.GetOp() << "\n"; } canUnroll = false; break; @@ -152,8 +156,8 @@ void LoopUnrolling::SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -174,8 +178,8 @@ void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2New } // When loop unroll times more than two, use this function to update the preds and succs of duplicate loopbodys. -void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -194,23 +198,22 @@ void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2Ne } } -void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, - BB &curCopyBB, bool copyAllLoop) { +void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, BB &curCopyBB, bool copyAllLoop) { if (resetFreqForUnrollWithVar && copyAllLoop) { if (&curBB == &exitBB && &succ == *loop->inloopBB2exitBBs.begin()->second->begin()) { curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : 1); } if ((&curBB == loop->latch && &succ == loop->head) || (&curBB == &exitBB && &succ == loop->latch)) { - curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : - loop->head->GetFrequency() % replicatedLoopNum - 1); + curCopyBB.PushBackSuccFreq( + loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : loop->head->GetFrequency() % replicatedLoopNum - 1); } else { curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) % replicatedLoopNum); } } else { - profValid && resetFreqForAfterInsertGoto ? - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) : - curBB.GetEdgeFreq(&succ) - 1) : - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); + profValid &&resetFreqForAfterInsertGoto + ? curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) + : curBB.GetEdgeFreq(&succ) - 1) + : curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); } } @@ -252,10 +255,9 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_mapSetFrequency(succ->GetFrequency() % replicatedLoopNum); } } else { - resetFreqForAfterInsertGoto ? - newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : - succ->GetFrequency() - 1) : - newBB->SetFrequency(succ->GetFrequency()); + resetFreqForAfterInsertGoto + ? newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : succ->GetFrequency() - 1) + : newBB->SetFrequency(succ->GetFrequency()); } curCopyBB->AddSucc(*newBB); ResetFrequency(*curBB, *succ, exitBB, *curCopyBB, copyAllLoop); @@ -272,8 +274,8 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop) { +void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop) { CreateLableAndInsertLabelBB(newHeadBB, labelBBs); std::queue bbQue; bbQue.push(loop->head); @@ -308,13 +310,13 @@ void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &ol // Update frequency of old BB. void LoopUnrolling::ResetFrequency(BB &bb) { auto freq = bb.GetFrequency() / replicatedLoopNum; - if (freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { freq = 1; } bb.SetFrequency(static_cast(freq + partialCount)); for (size_t i = 0; i < bb.GetSucc().size(); ++i) { auto currFreq = bb.GetEdgeFreq(i) / replicatedLoopNum; - if (currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { currFreq = 1; } bb.SetEdgeFreq(bb.GetSucc(i), currFreq + partialCount); @@ -366,10 +368,10 @@ void LoopUnrolling::AddEdgeForExitBBLastNew2OldBBEmpty(BB &exitBB, std::unordere bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[bb], idx); if (profValid) { - resetFreqForAfterInsertGoto ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + resetFreqForAfterInsertGoto + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); } ResetOldLabel2NewLabel(old2NewBB, *bb, exitBB, newHeadBB); } @@ -383,10 +385,10 @@ void LoopUnrolling::AddEdgeForExitBB(BB &exitBB, std::unordered_map &o bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[lastNew2OldBB[bb]], idx); if (profValid) { - (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); firstResetForAfterInsertGoto = false; } ResetOldLabel2NewLabel2(old2NewBB, *bb, exitBB, newHeadBB); @@ -403,14 +405,14 @@ void LoopUnrolling::CopyAndInsertBB(bool isPartial) { ResetFrequency(*loop->head); ResetFrequency(); } - profValid && resetFreqForAfterInsertGoto ? - (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) : - newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) : - newHeadBB->SetFrequency(loop->head->GetFrequency()); + profValid &&resetFreqForAfterInsertGoto + ? (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) + : newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) + : newHeadBB->SetFrequency(loop->head->GetFrequency()); (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); if (isPartial) { partialSuccHead = newHeadBB; } @@ -654,7 +656,8 @@ bool LoopUnrolling::LoopPartialUnrollWithConst(uint64 tripCount) { uint32 index = 0; if (!DetermineUnrollTimes(index, true)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "CodeSize is too large" << "\n"; + LogInfo::MapleLogger() << "CodeSize is too large" + << "\n"; } return false; } @@ -710,8 +713,8 @@ void LoopUnrolling::CopyLoopForPartialAndPre(BB *&newHead, BB *&newExiting) { (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; resetFreqForUnrollWithVar = true; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); resetFreqForUnrollWithVar = false; for (auto bb : labelBBs) { if (bb->GetKind() == kBBCondGoto) { @@ -742,8 +745,8 @@ VarMeExpr *LoopUnrolling::CreateIndVarOrTripCountWithName(const std::string &nam } // i < tripcount / unrollTime -void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, - MeExpr &unrollTimeExpr, uint32 offset) { +void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, + uint32 offset) { for (auto &stmt : bb.GetMeStmts()) { bb.RemoveMeStmt(&stmt); } @@ -815,8 +818,8 @@ void LoopUnrolling::CopyLoopForPartial(BB &partialCondGoto, BB &exitedBB, BB &ex partialCondGoto.AddSucc(*partialHead); if (profValid) { partialCondGoto.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum); - partialCondGoto.SetFrequency(static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + - partialCondGoto.GetEdgeFreq(1))); + partialCondGoto.SetFrequency( + static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + partialCondGoto.GetEdgeFreq(1))); } CHECK_FATAL(partialCondGoto.GetKind() == kBBCondGoto, "must be partialCondGoto"); CHECK_FATAL(!partialCondGoto.GetMeStmts().empty(), "must not be empty"); @@ -976,17 +979,19 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) uint32 index = 0; if (!DetermineUnrollTimes(index, false)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "codesize is too large" << "\n"; + LogInfo::MapleLogger() << "codesize is too large" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with var" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with var" + << "\n"; } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); } if (!SplitCondGotoBB()) { return false; @@ -1007,8 +1012,8 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); } return true; } @@ -1022,7 +1027,7 @@ void LoopUnrollingExecutor::SetNestedLoop(const IdentifyLoops &meLoop, CHECK_NULL_FATAL(loop->parent); auto it = parentLoop.find(loop->parent); if (it == parentLoop.end()) { - parentLoop[loop->parent] = { loop }; + parentLoop[loop->parent] = {loop}; } else { parentLoop[loop->parent].insert(loop); } @@ -1065,7 +1070,8 @@ bool LoopUnrollingExecutor::PredIsOutOfLoopBB(const MeFunction &func, LoopDesc & return false; } -bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func, LoopDesc &loop, +bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop( + const MeFunction &func, LoopDesc &loop, const std::unordered_map> &parentLoop) const { // Only handle one nested loop. if (parentLoop.find(&loop) != parentLoop.end() && ProfileCheck(func)) { @@ -1083,7 +1089,8 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func CHECK_FATAL(headBB->GetPred().size() == 2, "head must has two preds"); if (!IsDoWhileLoop(func, loop)) { if (enableDebug) { - LogInfo::MapleLogger() << "While-do loop" << "\n"; + LogInfo::MapleLogger() << "While-do loop" + << "\n"; } return false; } @@ -1100,19 +1107,20 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { if (tripCount == kInvalidTripCount) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "tripCount is invalid" << "\n"; + LogInfo::MapleLogger() << "tripCount is invalid" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "start unrolling with const" << "\n"; + LogInfo::MapleLogger() << "start unrolling with const" + << "\n"; LogInfo::MapleLogger() << "tripCount: " << tripCount << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + std::to_string(loop->head->GetBBId())); } // fully unroll ReturnKindOfFullyUnroll returnKind = LoopFullyUnroll(static_cast(tripCount)); @@ -1121,13 +1129,14 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } if (returnKind == LoopUnrolling::kCanFullyUnroll) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "fully unrolling" << "\n"; + LogInfo::MapleLogger() << "fully unrolling" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() + ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + std::to_string(loop->head->GetBBId())); } return true; } @@ -1137,12 +1146,13 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { // partial unroll with const if (LoopPartialUnrollWithConst(tripCount)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with const" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with const" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); } return true; } @@ -1150,7 +1160,8 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc) { + std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc) { if (enableDebug) { LogInfo::MapleLogger() << func.GetName() << "\n"; } @@ -1168,6 +1179,9 @@ void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMa } LoopScalarAnalysisResult sa(irMap, loop); LoopUnrolling loopUnrolling(func, *loop, irMap, alloc, cands); + if (func.GetCfg()->UpdateCFGFreq()) { + loopUnrolling.SetInstrumentProf(true); + } uint64 tripCount = 0; CRNode *conditionCRNode = nullptr; CR *itCR = nullptr; @@ -1236,6 +1250,9 @@ bool MELoopUnrolling::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-meloopunroll", false, true); + } } if (DEBUGFUNC_NEWPM(f)) { f.GetCfg()->DumpToFile("afterloopunrolling", false); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 1aa4bc9f5d..0041c51b0d 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -13,10 +13,12 @@ * See the Mulan PSL v2 for more details. */ #include "me_profile_use.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_function.h" +#include "me_option.h" namespace maple { BBUseInfo *MeProfUse::GetOrCreateBBUseInfo(const BB &bb) { @@ -206,8 +208,8 @@ bool MeProfUse::BuildEdgeCount() { uint64 hash = ComputeFuncHash(); if (hash != result.funcHash) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " - << result.funcHash << " func real hash " << hash << '\n'; + LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " << result.funcHash + << " func real hash " << hash << '\n'; } return false; } @@ -218,8 +220,8 @@ bool MeProfUse::BuildEdgeCount() { } if (instrumentBBs.size() != result.totalCounter) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << result.totalCounter << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << result.totalCounter + << " func real counter " << instrumentBBs.size() << '\n'; } return false; } @@ -294,12 +296,12 @@ bool MeProfUse::Run() { return true; } -GcovFuncInfo *MeProfUse::GetFuncData() { - GcovProfileData *gcovData = func->GetMIRModule().GetGcovProfile(); - if (!gcovData) { +FuncProfInfo *MeProfUse::GetFuncData() { + MplProfileData *profData = func->GetMIRModule().GetMapleProfile(); + if (!profData) { return nullptr; } - GcovFuncInfo *funcData = gcovData->GetFuncProfile(func->GetUniqueID()); + FuncProfInfo *funcData = profData->GetFuncProfile(func->GetUniqueID()); return funcData; } @@ -315,15 +317,15 @@ bool MeProfUse::CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, c return false; } -bool MeProfUse::GcovRun() { - GcovFuncInfo *funcData = GetFuncData(); +bool MeProfUse::MapleProfRun() { + FuncProfInfo *funcData = GetFuncData(); if (!funcData) { return false; } func->GetMirFunc()->SetFuncProfData(funcData); // early return if lineno fail if (CheckSumFail(ComputeLinenoHash(), funcData->linenoChecksum, "lineno")) { - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } FindInstrumentEdges(); @@ -336,12 +338,12 @@ bool MeProfUse::GcovRun() { if (dump) { DumpEdgeInfo(); } - if (instrumentBBs.size() != funcData->numCounts) { + if (instrumentBBs.size() != funcData->edgeCounts) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << funcData->numCounts << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << funcData->edgeCounts + << " func real counter " << instrumentBBs.size() << '\n'; } - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } size_t i = 0; @@ -368,16 +370,23 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { MeProfUse profUse(f, *GetPhaseMemPool(), DEBUGFUNC_NEWPM(f)); bool result = true; if (Options::profileUse) { - result = profUse.GcovRun(); - f.GetCfg()->VerifyBBFreq(); + result = profUse.MapleProfRun(); + if (result) { + result = f.GetCfg()->VerifyBBFreq(); + if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; + } + } } else { profUse.Run(); } - if (result) { + if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "******************after profile use dump function******************\n"; profUse.DumpFuncCFGEdgeFreq(); - f.GetCfg()->DumpToFile("afterProfileUse", false, true); + } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-ProfileUse", false, true); } return true; } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index 33e4e5027a..19425f68fc 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -93,6 +93,10 @@ void ValueRangePropagation::Execute() { dealWithPhi = true; DealWithPhi(**bIt); dealWithPhi = false; + if (func.GetCfg()->UpdateCFGFreq()) { + // update edge frequency + (*bIt)->UpdateEdgeFreqs(false); + } for (auto it = (*bIt)->GetMeStmts().begin(); it != (*bIt)->GetMeStmts().end();) { bool deleteStmt = false; if (!onlyPropVR) { @@ -3132,9 +3136,20 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB UpdateProfile(*pred, bb, unreachableBB); } Insert2UnreachableBBs(unreachableBB); + // update frequency before cfg changed + int64_t removedFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + int idx = bb.GetSuccIndex(unreachableBB); + removedFreq = bb.GetSuccFreq()[idx]; + } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetSuccFreq(0, bb.GetFrequency()); + succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + unreachableBB.SetFrequency(0); + } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); if (loop == nullptr) { return; @@ -3505,6 +3520,12 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3517,7 +3538,16 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + int64_t removedFreq = 0; + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + removedFreq = condGotoBB.GetSuccFreq()[0]; + } condGotoBB.RemoveSucc(*succ0); + if (func.GetCfg()->UpdateCFGFreq()) { + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); } @@ -3675,10 +3705,22 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } return true; } if (CodeSizeIsOverflowOrTheOpOfStmtIsNotSupported(bb)) { @@ -3712,8 +3754,21 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( mergeAllFallthruBBs->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); + if (func.GetCfg()->UpdateCFGFreq()) { + mergeAllFallthruBBs->SetFrequency(edgeFreq); + mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } mergeAllFallthruBBs->AddSucc(trueBranch); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); CreateLabelForTargetBB(pred, *mergeAllFallthruBBs); @@ -3778,19 +3833,48 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + // transform may not be consistent with frequency value + updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + exitCopyFallthru->SetFrequency(edgeFreq); + exitCopyFallthru->PushBackSuccFreq(edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + ASSERT(updatedtrueFreq >= 0, "sanity check"); + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } return true; } auto *newBB = CreateNewGotoBBWithoutCondGotoStmt(bb); @@ -3804,9 +3888,21 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( newBB->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + newBB->SetFrequency(edgeFreq); + newBB->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); @@ -5024,6 +5120,13 @@ bool MEValueRangePropagation::PhaseRun(maple::MeFunction &f) { } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); GetAnalysisInfoHook()->ForceRunTransFormPhase(&MELoopCanon::id, f); + // update cfg frequency + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-valuerange" + std::to_string(f.vrpRuns), false, true); + } + } } // Run vrp twice when need check boundary and nullable pointer. if (MeOption::boundaryCheckMode != kNoCheck || MeOption::npeCheckMode != kNoCheck) { diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index 0c89b82851..abbb818c29 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -13,8 +13,9 @@ * See the Mulan PSL v2 for more details. */ #include "optimizeCFG.h" -#include "me_phase_manager.h" + #include "factory.h" +#include "me_phase_manager.h" namespace maple { namespace { @@ -23,27 +24,27 @@ const char *funcName = nullptr; std::string phaseName; #define LOG_BBID(BB) ((BB)->GetBBId().GetIdx()) -#define DEBUG_LOG() if (debug) \ -LogInfo::MapleLogger() << "[" << phaseName << "] " +#define DEBUG_LOG() \ + if (debug) LogInfo::MapleLogger() << "[" << phaseName << "] " // return {trueBB, falseBB} -std::pair GetTrueFalseBrPair(BB *bb) { +std::pair GetTrueFalseBrPair(BB *bb) { if (bb == nullptr) { - return { nullptr, nullptr }; + return {nullptr, nullptr}; } if (bb->GetKind() == kBBCondGoto) { auto *condBr = static_cast(bb->GetLastMe()); CHECK_FATAL(condBr, "condBr is nullptr!"); if (condBr->GetOp() == OP_brtrue) { - return { bb->GetSucc(1), bb->GetSucc(0) }; + return {bb->GetSucc(1), bb->GetSucc(0)}; } else { ASSERT(condBr->GetOp() == OP_brfalse, "only support brtrue/brfalse"); - return { bb->GetSucc(0), bb->GetSucc(1) }; + return {bb->GetSucc(0), bb->GetSucc(1)}; } } else if (bb->GetKind() == kBBGoto) { - return { bb->GetSucc(0), nullptr }; + return {bb->GetSucc(0), nullptr}; } - return { nullptr, nullptr }; + return {nullptr, nullptr}; } // Only one fallthru is allowed for a bb at most , but a bb may have be more than one fallthru pred @@ -82,7 +83,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { if (expr->GetMeOp() == kMeOpConst || expr->GetMeOp() == kMeOpVar) { return; } - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons exprSet.insert(expr); } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -100,7 +101,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { // expr not throw exception bool IsSafeExpr(const MeExpr *expr) { - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons return false; } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -123,8 +124,7 @@ bool IsSafeExpr(const MeExpr *expr) { bool IsSimpleImm(uint64 imm) { return ((imm & (static_cast(0xffff) << 48u)) == imm) || ((imm & (static_cast(0xffff) << 32u)) == imm) || - ((imm & (static_cast(0xffff) << 16u)) == imm) || - ((imm & (static_cast(0xffff))) == imm) || + ((imm & (static_cast(0xffff) << 16u)) == imm) || ((imm & (static_cast(0xffff))) == imm) || (((~imm) & (static_cast(0xffff) << 48u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 32u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 16u)) == ~imm) || @@ -135,12 +135,12 @@ bool IsSimpleImm(uint64 imm) { // if non-simple imm exist, return it, otherwise return 0 int64 GetNonSimpleImm(MeExpr *expr) { if (expr->GetMeOp() == kMeOpConst && IsPrimitiveInteger(expr->GetPrimType())) { - int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); + int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); if (!IsSimpleImm(static_cast(imm))) { return imm; } } - return 0; // 0 is a simple imm + return 0; // 0 is a simple imm } // Check if ftBB has only one regassign stmt, if regassign exists, return it, otherwise return nullptr @@ -150,7 +150,7 @@ AssignMeStmt *GetSingleAssign(BB *bb) { while (stmt != nullptr && stmt->GetOp() == OP_comment) { stmt = stmt->GetNextMeStmt(); } - if (stmt == nullptr) { // empty bb or has only comment stmt + if (stmt == nullptr) { // empty bb or has only comment stmt return nullptr; } if (stmt->GetOp() == OP_regassign || stmt->GetOp() == OP_dassign) { @@ -193,7 +193,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetPred().empty() && bb->GetSucc().empty() && phiNode.GetOpnds().size() == 1) { @@ -207,7 +207,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetBB() != &currBB; } case kMeOpIvar: { - auto &ivar = static_cast(expr); + auto &ivar = static_cast(expr); if (!IsAllOpndsNotDefByCurrBB(*ivar.GetBase(), currBB, infLoopCheck)) { return false; } @@ -249,8 +249,8 @@ bool IsAllOpndsNotDefByCurrBB(const MeStmt &stmt) { MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { if (IsCompareHasReverseOp(cond->GetOp())) { - return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), - *cond->GetOpnd(0), *cond->GetOpnd(1)); + return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), *cond->GetOpnd(0), + *cond->GetOpnd(1)); } return irmap->CreateMeExprUnary(OP_lnot, cond->GetPrimType(), *cond); } @@ -258,8 +258,7 @@ MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { // Is subSet a subset of superSet? template inline bool IsSubset(const std::set &subSet, const std::set &superSet) { - return std::includes(superSet.begin(), superSet.end(), - subSet.begin(), subSet.end()); + return std::includes(superSet.begin(), superSet.end(), subSet.begin(), subSet.end()); } // before : predCond ---> succCond @@ -269,7 +268,7 @@ bool IsSafeToMergeCond(MeExpr *predCond, MeExpr *succCond) { // Make sure succCond is not dependent on predCond // e.g. if (ptr != nullptr) if (*ptr), the second condition depends on the first one if (predCond == succCond) { - return true; // same expr + return true; // same expr } if (!IsSafeExpr(succCond)) { std::set predSet; @@ -316,9 +315,9 @@ std::unique_ptr GetVRForSimpleCmpExpr(const MeExpr &expr) { if (!IsPrimitiveInteger(opndType)) { return nullptr; } - Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 + Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 if (expr.GetOpnd(1)->GetMeOp() == kMeOpConst) { - MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); + MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); if (constVal->GetKind() != kConstInt) { return nullptr; } @@ -380,7 +379,7 @@ BB *GetCommonDest(BB *predBB, BB *succBB) { } if (psucc0 != succBB && psucc1 != succBB) { - return nullptr; // predBB has no branch to succBB + return nullptr; // predBB has no branch to succBB } BB *commonBB = (psucc0 == succBB) ? psucc1 : psucc0; if (commonBB == nullptr) { @@ -517,7 +516,7 @@ bool UnreachBBAnalysis(const maple::MeFunction &f) { } return false; } -} // anonymous namespace +} // anonymous namespace // contains only one valid goto stmt bool HasOnlyMeGotoStmt(BB &bb) { @@ -600,8 +599,8 @@ bool IsMplEmptyBB(BB &bb) { // connectingBB has only one pred and succ, and has no stmt (except a single gotoStmt) in it bool IsConnectingBB(BB &bb) { return (bb.GetPred().size() == 1 && bb.GetSucc().size() == 1) && - (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty - (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty + (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty + (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty } // RealSucc is a non-connecting BB which is not empty (or has just a single gotoStmt). @@ -664,8 +663,8 @@ void EliminateEmptyConnectingBB(const BB *predBB, BB *emptyBB, const BB *stopBB, while (emptyBB != nullptr && emptyBB != stopBB && IsConnectingBB(*emptyBB)) { BB *succ = emptyBB->GetSucc(0); BB *pred = emptyBB->GetPred(0); - DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) - << "(deleted)->BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) << "(deleted)->BB" + << LOG_BBID(succ) << "\n"; if (pred->IsPredBB(*succ)) { pred->RemoveSucc(*emptyBB, true); emptyBB->RemoveSucc(*succ, true); @@ -688,27 +687,33 @@ bool HasFallthruPred(const BB &bb) { class OptimizeBB { public: OptimizeBB(BB *bb, MeFunction &func, std::map>> *candidates) - : currBB(bb), f(func), cfg(func.GetCfg()), irmap(func.GetIRMap()), - irBuilder(func.GetMIRModule().GetMIRBuilder()), isMeIR(irmap != nullptr), cands(candidates) {} + : currBB(bb), + f(func), + cfg(func.GetCfg()), + irmap(func.GetIRMap()), + irBuilder(func.GetMIRModule().GetMIRBuilder()), + isMeIR(irmap != nullptr), + cands(candidates) {} // optimize each currBB until no change occur bool OptBBIteratively(); // initial factory to create corresponding optimizer for currBB according to BBKind. void InitBBOptFactory(); private: - BB *currBB = nullptr; // BB we currently perform optimization on - MeFunction &f; // function we currently perform optimization on - MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB - MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt - MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode + BB *currBB = nullptr; // BB we currently perform optimization on + MeFunction &f; // function we currently perform optimization on + MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB + MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt + MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode bool isMeIR = false; - std::map>> *cands = nullptr; // candidates ost need to be updated ssa - std::map> candsOstInBB; // bb with ost needed to be updated - - bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization - // opportunity for currBB after a/some optimization, we should set it true. - // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat { + std::map>> *cands = nullptr; // candidates ost need to be updated ssa + std::map> candsOstInBB; // bb with ost needed to be updated + + bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization + // opportunity for currBB after a/some optimization, we should set it true. + // Otherwise it will stop after all optimizations finished and continue to nextBB. + enum BBErrStat + { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -792,23 +797,23 @@ class OptimizeBB { repeatOpt = false; } #define CHECK_CURR_BB() \ -if (!CheckCurrBB()) { \ - return false; \ -} + if (!CheckCurrBB()) { \ + return false; \ + } #define ONLY_FOR_MEIR() \ -if (!isMeIR) { \ - return false; \ -} + if (!isMeIR) { \ + return false; \ + } }; -using OptBBFatory = FunctionFactory; +using OptBBFatory = FunctionFactory; bool OptimizeBB::CheckCurrBB() { - if (bbErrStat != kBBNoErr) { // has been checked before + if (bbErrStat != kBBNoErr) { // has been checked before return false; } - if (currBB == nullptr) { + if (currBB == nullptr) { bbErrStat = kBBErrNull; return false; } @@ -832,9 +837,9 @@ bool OptimizeBB::CheckCurrBB() { void OptimizeBB::UpdateBBIdInSSACand(const BBId &oldBBID, const BBId &newBBID) { auto it = candsOstInBB.find(oldBBID); if (it == candsOstInBB.end()) { - return; // no item to update + return; // no item to update } - auto &ostSet = candsOstInBB[newBBID]; // find or create + auto &ostSet = candsOstInBB[newBBID]; // find or create ostSet.insert(it->second.begin(), it->second.end()); candsOstInBB.erase(it); for (auto &cand : *cands) { @@ -854,7 +859,7 @@ void OptimizeBB::UpdateSSACandForBBPhiList(BB *bb, const BB *newBB) { if (!isMeIR || bb == nullptr || bb->GetMePhiList().empty()) { return; } - if (newBB == nullptr) { // if not specified, newBB is bb itself + if (newBB == nullptr) { // if not specified, newBB is bb itself newBB = bb; } std::set &ostSet = candsOstInBB[newBB->GetBBId()]; @@ -942,18 +947,18 @@ bool OptimizeBB::BranchBB2UncondBB(BB &bb) { } } - DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") - << "BB" << LOG_BBID(&bb) << " to unconditional BB\n"; + DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") << "BB" + << LOG_BBID(&bb) << " to unconditional BB\n"; // delete all empty bb between bb and destBB // note : bb and destBB will be connected after empty BB is deleted for (int i = static_cast(bb.GetSucc().size()) - 1; i >= 0; --i) { EliminateEmptyConnectingBB(&bb, bb.GetSucc(static_cast(i)), destBB, *cfg); } - while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 + while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 ASSERT(bb.GetSucc().back() == destBB, "[FUNC: %s]Goto BB%d has different destination", funcName, LOG_BBID(&bb)); bb.RemoveSucc(*bb.GetSucc().back()); } - if (Options::profileUse && !bb.GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { ASSERT(bb.GetSuccFreq().size() == bb.GetSucc().size(), "sanity check"); bb.SetSuccFreq(0, bb.GetFrequency()); } @@ -1011,30 +1016,32 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { CHECK_FATAL(brStmt, "brStmt is nullptr!"); bool isCondTrue = (!condExpr->IsZero()); bool isBrtrue = (brStmt->GetOp() == OP_brtrue); - if (isCondTrue != isBrtrue) { // goto fallthru BB + if (isCondTrue != isBrtrue) { // goto fallthru BB currBB->RemoveLastMeStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB, true); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { MeStmt *gotoStmt = irmap->CreateGotoMeStmt(f.GetOrCreateBBLabel(*gtBB), currBB, &brStmt->GetSrcPosition()); currBB->ReplaceMeStmt(brStmt, gotoStmt); currBB->SetKind(kBBGoto); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB, true); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1050,25 +1057,27 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { if (isCondTrue != isBrTrue) { currBB->RemoveLastStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { StmtNode *gotoStmt = irBuilder->CreateStmtGoto(OP_goto, f.GetOrCreateBBLabel(*gtBB)); currBB->ReplaceStmt(&brStmt, gotoStmt); currBB->SetKind(kBBGoto); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1151,11 +1160,15 @@ bool OptimizeBB::RemoveSuccFromNoReturnBB() { if (phiNode->GetOpnds().size() < 1) { break; } - phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum + phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum } } (void)EliminateRedundantPhiList(retBB); ResetBBRunAgain(); + // add edge Frequency to exitbb + if (cfg->UpdateCFGFreq()) { + currBB->PushBackSuccFreq(0); + } } return true; } @@ -1207,15 +1220,14 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { } } // update succFreqs before update succs - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData() && - !succ->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq() && !succ->GetSuccFreq().empty()) { // copy succFreqs of succ to pred for (int i = 0; i < succ->GetSuccFreq().size(); i++) { pred->PushBackSuccFreq(succ->GetSuccFreq()[i]); } } succ->MoveAllSuccToPred(pred, cfg->GetCommonExitBB()); - pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. + pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. if (!isSuccEmpty) { // only when we move stmt from succ to pred should we set attr and kind here pred->SetAttributes(succ->GetAttributes()); @@ -1239,11 +1251,11 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { // update bbid : tell ssa-updater to update with new BBID UpdateBBIdInSSACand(succ->GetBBId(), pred->GetBBId()); } - DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) - << ", and delete BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) << ", and delete BB" << LOG_BBID(succ) + << "\n"; UpdateSSACandForBBPhiList(succ, pred); DeleteBB(succ); - succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. + succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. return pred; } @@ -1286,13 +1298,13 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE if (trueExpr == falseExpr) { return true; } - ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName) ; - ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName) ; + ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName); + ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName); // try to simplify select expr MeExpr *selExpr = irmap->CreateMeExprSelect(trueExpr->GetPrimType(), *condExpr, *trueExpr, *falseExpr); MeExpr *simplifiedSel = irmap->SimplifyMeExpr(selExpr); if (simplifiedSel != selExpr) { - return true; // can be simplified + return true; // can be simplified } // We can check for every opnd of opndExpr, and calculate their cost according to cg's insn @@ -1317,30 +1329,30 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE return true; } - // Ignoring connecting BB, two cases can be turn into select - // condBB condBB - // / \ / \ +// Ignoring connecting BB, two cases can be turn into select +// condBB condBB +// / \ / \ // ftBB gtBB | gtBB/ftBB - // x<- x<- | x<- - // \ / \ / - // jointBB jointBB +// x<- x<- | x<- +// \ / \ / +// jointBB jointBB bool OptimizeBB::CondBranchToSelect() { CHECK_CURR_BB(); - BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB - BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB + BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB + BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB if (ftBB == gtBB) { (void)BranchBB2UncondBB(*currBB); return true; } // if ftBB or gtBB itself is jointBB, just return itself; otherwise return real succ - BB *ftTargetBB = (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) - : ftBB; - BB *gtTargetBB = (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) - : gtBB; + BB *ftTargetBB = + (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) : ftBB; + BB *gtTargetBB = + (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) : gtBB; if (ftTargetBB != gtTargetBB) { return false; } - BB *jointBB = ftTargetBB; // common succ + BB *jointBB = ftTargetBB; // common succ // Check if ftBB has only one assign stmt, set ftStmt if a assign stmt exist AssignMeStmt *ftStmt = nullptr; if (ftBB != jointBB) { @@ -1365,7 +1377,7 @@ bool OptimizeBB::CondBranchToSelect() { // Here we found a pattern, collect select opnds and result reg ScalarMeExpr *ftLHS = nullptr; MeExpr *ftRHS = nullptr; - std::set chiListCands; // collect chilist if assign stmt has one + std::set chiListCands; // collect chilist if assign stmt has one if (ftStmt != nullptr) { ftLHS = static_cast(ftStmt->GetLHS()); ftRHS = ftStmt->GetRHS(); @@ -1413,9 +1425,9 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because two ost assigned are not the same\n"; return false; } - DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) - << ", BB" << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; - if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety + DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) << ", BB" + << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; + if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety // black list if (!IsSafeExpr(ftRHS) || !IsSafeExpr(gtRHS)) { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because trueExpr or falseExpr is not safe\n"; @@ -1434,7 +1446,7 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Condition To Select : BB" << LOG_BBID(currBB) << "(cond)->[BB" << LOG_BBID(ftBB) << "(ft), BB" << LOG_BBID(gtBB) << "(gt)]->BB" << LOG_BBID(jointBB) << "(joint)\n"; ScalarMeExpr *resLHS = nullptr; - if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. + if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. // use phinode lhs as result auto it = jointBB->GetMePhiList().find(ftLHS->GetOstIdx()); if (it == jointBB->GetMePhiList().end()) { @@ -1448,7 +1460,7 @@ bool OptimizeBB::CondBranchToSelect() { // It is profitable for instruction selection if select opnd is a compare expression // select condExpr, trueExpr, falseExpr => select cmpExpr, trueExpr, falseExpr if (condExpr->IsScalar() && condExpr->GetPrimType() != PTY_u1) { - auto *scalarExpr = static_cast(condExpr); + auto *scalarExpr = static_cast(condExpr); if (scalarExpr->GetDefBy() == kDefByStmt) { MeStmt *defStmt = scalarExpr->GetDefStmt(); MeExpr *rhs = defStmt->GetRHS(); @@ -1473,7 +1485,7 @@ bool OptimizeBB::CondBranchToSelect() { } (void)BranchBB2UncondBB(*currBB); // update phi - if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred + if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred // just remove phinode jointBB->GetMePhiList().erase(resLHS->GetOstIdx()); } else { @@ -1517,11 +1529,11 @@ bool IsExprSameLexicalally(MeExpr *expr1, MeExpr *expr2) { if (const1->GetKind() == kConstInt) { return static_cast(const1)->GetExtValue() == static_cast(const2)->GetExtValue(); } else if (const1->GetKind() == kConstFloatConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } else if (const1->GetKind() == kConstDoubleConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } return false; } @@ -1707,18 +1719,18 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { } MeExpr *predCond = predBr->GetOpnd(0); MeExpr *succCond = succBr->GetOpnd(0); - auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false - auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false + auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false + auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false // Try to infer result of succCond from predCond bool isPredTrueBrSucc = (FindFirstRealSucc(ptfSucc.first) == &succ); BranchResult tfBranch = InferSuccCondBrFromPredCond(predCond, succCond, isPredTrueBrSucc); - if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond + if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond return false; } // if succ's cond can be inferred from pred's cond, pred can skip succ and branches to newTarget directly BB *newTarget = (tfBranch == kBrTrue) ? FindFirstRealSucc(stfSucc.first) : FindFirstRealSucc(stfSucc.second); if (newTarget == nullptr || newTarget == &succ) { - return false; + return false; } DEBUG_LOG() << "Condition in BB" << LOG_BBID(&succ) << " is redundant, since it has been checked in BB" << LOG_BBID(&pred) << ", BB" << LOG_BBID(&pred) << " can branch to BB" << LOG_BBID(newTarget) << "\n"; @@ -1728,7 +1740,7 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { // succ ... // / \ // ftBB gtBB - if (succ.GetPred().size() == 1) { // succ has only one pred + if (succ.GetPred().size() == 1) { // succ has only one pred // if newTarget is succ's gotoBB, and it has fallthru pred, we should add a goto stmt to succ's last // to replace condGoto stmt. Otherwise, newTarget will have two fallthru pred if (newTarget == FindFirstRealSucc(succ.GetSucc(1)) && HasFallthruPred(*newTarget)) { @@ -1746,7 +1758,17 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { DEBUG_LOG() << "SkipRedundantCond : Remove condBr in BB" << LOG_BBID(&succ) << ", turn it to fallthruBB\n"; } BB *rmBB = (FindFirstRealSucc(succ.GetSucc(0)) == newTarget) ? succ.GetSucc(1) : succ.GetSucc(0); + int64_t deletedSuccFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = succ.GetSuccIndex(*rmBB); + deletedSuccFreq = succ.GetSuccFreq()[idx]; + } succ.RemoveSucc(*rmBB, true); + if (cfg->UpdateCFGFreq()) { + succ.SetSuccFreq(0, succ.GetFrequency()); + auto *succofSucc = succ.GetSucc(0); + succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; } else { @@ -1784,18 +1806,19 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { BB *replacedSucc = isPredTrueBrSucc ? ptfSucc.first : ptfSucc.second; EliminateEmptyConnectingBB(&pred, replacedSucc, &succ, *cfg); ASSERT(pred.IsPredBB(succ), "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName); - int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred - pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it + int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred + pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it DEBUG_LOG() << "Replace succ BB" << LOG_BBID(replacedSucc) << " with BB" << LOG_BBID(newBB) << ": BB" - << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" << " => BB" << LOG_BBID(&pred) - << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) << "\n"; + << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" + << " => BB" << LOG_BBID(&pred) << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) + << "\n"; if (pred.GetSucc(1) == newBB) { cfg->UpdateBranchTarget(pred, succ, *newBB, f); } newTarget->AddPred(*newBB); UpdatePhiForMovingPred(predPredIdx, newBB, &succ, newTarget); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + if (cfg->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -1806,6 +1829,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { uint32_t freqOfSucc = succ.GetFrequency(); ASSERT(freqOfSucc >= freq, "sanity check"); succ.SetFrequency(freqOfSucc - freq); + // update edge frequency + BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; + idx = succ.GetSuccIndex(*affectedBB); + ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); + int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + ASSERT(oldedgeFreq >= freq, "sanity check"); + succ.SetSuccFreq(idx, (oldedgeFreq - freq)); } return true; } @@ -1894,7 +1924,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * // create a new version for new phi phiMeNode->SetLHS(irmap->CreateRegOrVarMeExprVersion(ostIdx)); } - UpdateSSACandForBBPhiList(succ); // new philist has been created in succ + UpdateSSACandForBBPhiList(succ); // new philist has been created in succ } else { // succ has other pred besides curr for (auto &phi : succPhiList) { @@ -1924,7 +1954,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * } else { auto *phiMeNode = irmap->NewInPool(); phiMeNode->SetDefBB(succ); - resPair.first->second = phiMeNode; // replace nullptr inserted before + resPair.first->second = phiMeNode; // replace nullptr inserted before auto &phiOpnds = phiMeNode->GetOpnds(); // insert opnd into New phiNode : all phiOpnds (except for pred) are phiNode lhs in curr phiOpnds.insert(phiOpnds.end(), succ->GetPred().size(), phi.second->GetLHS()); @@ -1963,7 +1993,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (!HasOnlyMeGotoStmt(*succ)) { return false; } - BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB + BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB if (newTarget == succ) { // succ goto itself, no need to update goto target to newTarget return false; @@ -1975,8 +2005,8 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { // pred is moved to newTarget if (pred->GetKind() == kBBFallthru) { CHECK_FATAL(succ->GetLastMe(), "LastMe is nullptr!"); - GotoMeStmt *gotoMeStmt = irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, - &succ->GetLastMe()->GetSrcPosition()); + GotoMeStmt *gotoMeStmt = + irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, &succ->GetLastMe()->GetSrcPosition()); pred->AddMeStmtLast(gotoMeStmt); pred->SetKind(kBBGoto); DEBUG_LOG() << "Insert Uncond stmt to fallthru BB" << LOG_BBID(currBB) << ", and goto BB" << LOG_BBID(newTarget) @@ -1984,15 +2014,29 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { } int predIdx = succ->GetPredIndex(*pred); bool needUpdatePhi = false; + int64_t removedFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*succ); + removedFreq = pred->GetSuccFreq()[idx]; + } if (pred->IsPredBB(*newTarget)) { - pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*newTarget); + pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + } } else { - pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later + pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later needUpdatePhi = true; } - - DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) - << ": BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; + if (cfg->UpdateCFGFreq()) { + int64_t succFreq = succ->GetFrequency(); + ASSERT(succFreq >= removedFreq, "sanity check"); + succ->SetFrequency(succFreq - removedFreq); + succ->SetSuccFreq(0, succ->GetFrequency()); + } + DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) + << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; cfg->UpdateBranchTarget(*pred, *succ, *newTarget, f); if (needUpdatePhi) { // remove phiOpnd in succ, and add phiOpnd to newTarget @@ -2034,7 +2078,7 @@ bool OptimizeBB::OptimizeUncondBB() { return false; } // wont exit BB and has an edge to commonExit, if we merge it to pred and delete it, the egde will be cut off - if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit + if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit ASSERT(currBB->GetAttributes(kBBAttrWontExit), "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName, LOG_BBID(currBB)); return false; @@ -2096,11 +2140,11 @@ bool OptimizeBB::OptimizeSwitchBB() { if (swStmt->GetOpnd()->GetMeOp() != kMeOpConst) { return false; } - auto *swConstExpr = static_cast(swStmt->GetOpnd()); + auto *swConstExpr = static_cast(swStmt->GetOpnd()); MIRConst *swConstVal = swConstExpr->GetConstVal(); ASSERT(swConstVal->GetKind() == kConstInt, "[FUNC: %s]switch is only legal for integer val", funcName); int64 val = static_cast(swConstVal)->GetExtValue(); - BB *survivor = currBB->GetSucc(0); // init as default BB + BB *survivor = currBB->GetSucc(0); // init as default BB for (size_t i = 0; i < swStmt->GetSwitchTable().size(); ++i) { int64 caseVal = swStmt->GetSwitchTable().at(i).first; if (caseVal == val) { @@ -2157,8 +2201,8 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { MeExpr *geConst = geExpr->GetOpnd(1); PrimType lePtyp = leConst->GetPrimType(); PrimType gePtyp = geConst->GetPrimType(); - if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || - lePtyp != gePtyp || !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around + if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || lePtyp != gePtyp || + !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around return nullptr; } int64 leVal = static_cast(static_cast(leConst)->GetConstVal())->GetExtValue(); @@ -2174,9 +2218,9 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { (IsPrimitiveUnsigned(lePtyp) && static_cast(leVal) > static_cast(newGeVal))) { // e.g. x < 3 || x > 2 <==> true return irmap->CreateIntConstMeExpr(1, PTY_u1); - } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 - return irmap->CreateMeExprCompare( - OP_ne, PTY_u1, opndPtyp, *sameExpr, *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); + } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 + return irmap->CreateMeExprCompare(OP_ne, PTY_u1, opndPtyp, *sameExpr, + *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); } // (x < val1 || x > val2) <==> ((unsigned)(x - val1) > (val2 - val1)) MeExpr *newLeConst = irmap->CreateIntConstMeExpr(leVal, opndPtyp); @@ -2255,15 +2299,15 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { return false; } if (!IsProfitableToMergeCond(predCond, succCond)) { - DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" - << LOG_BBID(succ) << " is not simple enough and not profitable\n"; + DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" << LOG_BBID(succ) + << " is not simple enough and not profitable\n"; return false; } // Start trying to merge two condition together if possible - auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches - auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches + auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches + auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches Opcode combinedCondOp = OP_undef; - bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) + bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) // all cases are listed as follow: // | case | predBB -> common | succBB -> common | invertSuccCond | or/and | // | ---- | ---------------- | ---------------- | -------------- | ------ | @@ -2275,16 +2319,16 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // pred's false branch to succ, so true branch to common bool isPredTrueToCommon = (FindFirstRealSucc(ptfBrPair.second) == succ); bool isSuccTrueToCommon = (FindFirstRealSucc(stfBrPair.first) == commonBB); - if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 + if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 invertSuccCond = false; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 + } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 invertSuccCond = false; combinedCondOp = OP_land; - } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 + } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 invertSuccCond = true; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 + } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 invertSuccCond = true; combinedCondOp = OP_land; } else { @@ -2311,7 +2355,7 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // remove succ and update cfg BB *exitBB = isSuccTrueToCommon ? stfBrPair.second : stfBrPair.first; pred->ReplaceSucc(succ, exitBB); - exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. + exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. // we should eliminate edge from succ to commonBB BB *toEliminateBB = isSuccTrueToCommon ? stfBrPair.first : stfBrPair.second; EliminateEmptyConnectingBB(succ, toEliminateBB, commonBB /* stop here */, *cfg); @@ -2354,6 +2398,11 @@ bool OptimizeBB::FoldBranchToCommonDest() { bool OptimizeBB::OptBBOnce() { CHECK_CURR_BB(); DEBUG_LOG() << "Try to optimize BB" << LOG_BBID(currBB) << "...\n"; + // bb frequency may be updated, make bb frequency and succs frequency consistent + // skip deadBB + if (cfg->UpdateCFGFreq() && (!currBB->GetPred().empty()) && (currBB->GetUniquePred() != currBB)) { + currBB->UpdateEdgeFreqs(false); + } bool everChanged = false; // eliminate dead BB : // 1.BB has no pred(expect then entry block) @@ -2416,7 +2465,7 @@ class OptimizeFuntionCFG { private: MeFunction &f; - std::map>> *cands = nullptr; // candidates ost need to update ssa + std::map>> *cands = nullptr; // candidates ost need to update ssa bool OptimizeFuncCFGIteratively(); bool OptimizeCFGForBB(BB *currBB); }; @@ -2439,10 +2488,6 @@ bool OptimizeFuntionCFG::OptimizeFuncCFGIteratively() { if (currBB == nullptr) { continue; } - // bb frequency may be updated, make bb frequency and succs frequency consistent - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { - currBB->UpdateEdgeFreqs(); - } changed |= OptimizeCFGForBB(currBB); } everChanged |= changed; @@ -2488,15 +2533,14 @@ bool OptimizeMeFuncCFG(maple::MeFunction &f, std::mapValidBBNum(); // optimization entry - bool change = OptimizeFuntionCFG(f, ssaCand) - .OptimizeOnFunc(); + bool change = OptimizeFuntionCFG(f, ssaCand).OptimizeOnFunc(); if (change) { f.GetCfg()->WontExitAnalysis(); if (debug) { uint32 bbNumAfter = f.GetCfg()->ValidBBNum(); if (bbNumBefore != bbNumAfter) { - DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") - << " from " << bbNumBefore << " to " << bbNumAfter << "\n"; + DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") << " from " << bbNumBefore + << " to " << bbNumAfter << "\n"; } else { DEBUG_LOG() << "BBs' number keep the same as before (num = " << bbNumAfter << ")\n"; } @@ -2517,6 +2561,9 @@ bool MEOptimizeCFGNoSSA::PhaseRun(MeFunction &f) { debug = DEBUGFUNC_NEWPM(f); phaseName = PhaseName(); bool change = OptimizeMeFuncCFG(f, nullptr); + if (change && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFGNOSSA", false, f.GetCfg()->UpdateCFGFreq()); + } return change; } @@ -2542,7 +2589,10 @@ bool MEOptimizeCFG::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFG", false, f.GetCfg()->UpdateCFGFreq()); + } } return change; } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_util/BUILD.gn b/src/mapleall/maple_util/BUILD.gn index a7341eae06..09f912369e 100755 --- a/src/mapleall/maple_util/BUILD.gn +++ b/src/mapleall/maple_util/BUILD.gn @@ -27,6 +27,7 @@ src_libmplutil = [ "src/error_code.cpp", "src/thread_env.cpp", "src/mpl_int_val.cpp", + "src/mpl_profdata.cpp" ] src_libcommandline = [ diff --git a/src/mapleall/maple_util/include/mpl_profdata.h b/src/mapleall/maple_util/include/mpl_profdata.h new file mode 100644 index 0000000000..23cf6f99b9 --- /dev/null +++ b/src/mapleall/maple_util/include/mpl_profdata.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#define MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#include +#include +#include "mempool_allocator.h" + +namespace maple { +constexpr uint32_t HOTCALLSITEFREQ = 100; +enum UpdateFreqOp { + kKeepOrigFreq = 0, + kUpdateOrigFreq = 0x1, + kUpdateFreqbyScale = 0x2, + kUpdateUnrolledFreq = 0x4, + kUpdateUnrollRemainderFreq = 0x8, +}; + +// used for record cumulative datas +struct ProfileSummaryHistogram { + uint32_t countRatio; + uint32_t startValue; // count value range in [startValue, nextHistogramStart) + uint32_t countNums; // Number of counters whose profile count falls in countValue range. + uint64_t countMinVal; // Smallest profile count included in this range. + uint64_t countCumValue; // Cumulative value of the profile counts + + ProfileSummaryHistogram(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) + : countRatio(0), startValue(s), countNums(num), countMinVal(mincount), countCumValue(cumcounts) {} +}; + +class ProfileSummary { + public: + explicit ProfileSummary(MapleAllocator *alloc) : histogram(alloc->Adapter()) {} + ProfileSummary(MapleAllocator *alloc, uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, + uint64_t sumcount) + : checkSum(checksum), + run(runtimes), + totalCount(totalcount), + maxCount(maxcount), + sumCount(sumcount), + histogram(alloc->Adapter()) {} + + void SetSummary(uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, uint64_t sumcount) { + checkSum = checksum; + run = runtimes; + totalCount = totalcount; + maxCount = maxcount; + sumCount = sumcount; + } + void AddHistogramRecord(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) { + histogram.push_back(ProfileSummaryHistogram(s, num, mincount, cumcounts)); + } + void DumpSummary(); + uint64_t GetCheckSum() { + return checkSum; + } + uint32_t GetRun() { + return run; + } + uint32_t GetTotalCount() { + return totalCount; + } + uint64_t GetMaxCount() { + return maxCount; + } + uint64_t GetSumCount() { + return sumCount; + } + uint32_t GetHistogramLength() { + return histogram.size(); + } + void ProcessHistogram(); + MapleVector &GetHistogram() { + return histogram; + } + + private: + uint64_t checkSum; // checksum value of module + uint32_t run; // run times + uint32_t totalCount; // number of counters + uint64_t maxCount; // max counter value in single run + uint64_t sumCount; // sum of all counters accumulated. + MapleVector histogram; // record gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; +}; + +class FuncProfInfo { + public: + FuncProfInfo(MapleAllocator *alloc, unsigned funcIdent, unsigned linenoCs, unsigned cfgCs, unsigned countnum = 0) + : ident(funcIdent), + linenoChecksum(linenoCs), + cfgChecksum(cfgCs), + edgeCounts(countnum), + counts(alloc->Adapter()){}; + ~FuncProfInfo() = default; + + uint64_t GetFuncFrequency() const { + return entryFreq; + } + void SetFuncFrequency(uint64_t freq) { + entryFreq = freq; + } + + uint64_t GetFuncRealFrequency() const { + return realEntryfreq; + } + void SetFuncRealFrequency(uint64_t freq) { + realEntryfreq = freq; + } + + std::unordered_map &GetStmtFreqs() { + return stmtFreqs; + } + uint64_t GetStmtFreq(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + return stmtFreqs[stmtID]; + } + return -1; // unstored + } + void SetStmtFreq(uint32_t stmtID, uint64_t freq) { + stmtFreqs[stmtID] = freq; + } + void EraseStmtFreq(uint32_t stmtID) { + stmtFreqs.erase(stmtID); + } + void CopyStmtFreq(uint32_t newStmtID, uint32_t origStmtId, bool deleteOld = false) { + ASSERT(GetStmtFreq(origStmtId) >= 0, "origStmtId no freq record"); + SetStmtFreq(newStmtID, GetStmtFreq(origStmtId)); + if (deleteOld) { + EraseStmtFreq(origStmtId); + } + } + bool IsHotCallSite(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + uint64_t freq = stmtFreqs[stmtID]; + return (freq >= HOTCALLSITEFREQ); + } + ASSERT(0, "should not be here"); + return false; + } + void DumpFunctionProfile(); + + unsigned ident; + unsigned linenoChecksum; + unsigned cfgChecksum; + + // Raw arc coverage counts. + unsigned edgeCounts; + MapleVector counts; + uint64_t entryFreq; // record entry bb frequence + std::unordered_map stmtFreqs; // stmt_id is key, counter value + uint64_t realEntryfreq; // function prof data may be modified after clone/inline +}; + +class MplProfileData { + public: + MplProfileData(MemPool *m, MapleAllocator *a) : funcsCounter(a->Adapter()), summary(a), mp(m), alloc(a) {} + + FuncProfInfo *GetFuncProfile(unsigned puidx) { + if (funcsCounter.count(puidx) > 0) { + return funcsCounter[puidx]; + } + return nullptr; + } + FuncProfInfo *AddNewFuncProfile(unsigned puidx, unsigned linoCs, unsigned cfgCs, unsigned countnum) { + FuncProfInfo *funcProf = mp->New(alloc, puidx, linoCs, cfgCs, countnum); + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcProf; + return funcProf; + } + void AddFuncProfile(unsigned puidx, FuncProfInfo *funcData) { + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcData; + } + void DumpProfileData(); + void DumpFunctionsProfile(); + bool IsHotCallSite(uint64_t freq); + + MapleUnorderedMap funcsCounter; // use puidx as key + // record module profile information and statistics of count information + ProfileSummary summary; + uint64_t hotCountThreshold = 0; + + private: + uint64_t GetHotThreshold(); + + MemPool *mp; + MapleAllocator *alloc; +}; +} // namespace maple +#endif // MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index 250e9ef8ba..c3333b16cf 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -190,6 +190,7 @@ static constexpr const char kBindingProtectedRegionStr[] = "__BindingProtectRegi static constexpr const char kClassNamePrefixStr[] = "L"; static constexpr const char kClassMethodSplitterStr[] = "_3B"; static constexpr const char kFuncGetCurrentCl[] = "MCC_GetCurrentClassLoader"; +static constexpr const char kMplProfFileNameExt[] = ".mprofdata"; // Serve as a global flag to indicate whether frequent strings have been compressed extern bool doCompression; @@ -212,6 +213,10 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); } // namespace namemangler #endif diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp new file mode 100644 index 0000000000..849b262239 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ +#include "mpl_profdata.h" + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { +void ProfileSummary::DumpSummary() { + LogInfo::MapleLogger() << "---------ProfileSummary-------------- \n"; + LogInfo::MapleLogger() << " checkSum: " << std::hex << "0x" << checkSum << "\n"; + LogInfo::MapleLogger() << " runtimes: " << std::dec << run << "\n"; + LogInfo::MapleLogger() << " totalCounts: " << std::dec << totalCount << "\n"; + LogInfo::MapleLogger() << " maxCount: " << std::dec << maxCount << "\n"; + LogInfo::MapleLogger() << " count histogram: countRange countNum minCount cumCount \n"; + for (auto &it : histogram) { + LogInfo::MapleLogger() << " " << std::dec << it.startValue << "\t"; + LogInfo::MapleLogger() << std::dec << it.countNums << "\t" << it.countMinVal << "\t" << it.countCumValue << "\n"; + } +} + +void FuncProfInfo::DumpFunctionProfile() { + LogInfo::MapleLogger() << "function ident " << std::dec << ident; + LogInfo::MapleLogger() << " lino_checksum 0x" << std::hex << linenoChecksum << ", "; + LogInfo::MapleLogger() << " cfg_checksum 0x" << std::hex << cfgChecksum << "\n"; + LogInfo::MapleLogger() << " num_counts " << std::dec << edgeCounts << " : "; + for (unsigned i = 0; i < edgeCounts; i++) { + LogInfo::MapleLogger() << std::dec << " " << counts[i]; + } + LogInfo::MapleLogger() << "\n"; +} + +void MplProfileData::DumpFunctionsProfile() { + LogInfo::MapleLogger() << "---------FunctionProfile-------------- \n"; + for (auto &it : funcsCounter) { + it.second->DumpFunctionProfile(); + } +} + +void MplProfileData::DumpProfileData() { + summary.DumpSummary(); + DumpFunctionsProfile(); +} + +void ProfileSummary::ProcessHistogram() { + int countsum = 0; + int n = histogram.size(); + for (int i = n - 1; i >= 0; i--) { + countsum += histogram[i].countNums; + histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + } +} + +#define HOTRATIO 90 +uint64_t MplProfileData::GetHotThreshold() { + for (auto &it : summary.GetHistogram()) { + if (it.countRatio >= HOTRATIO) { + hotCountThreshold = it.startValue; + } else { + if (hotCountThreshold == 0) { + hotCountThreshold = it.countMinVal; // set minValue in currentRange which satisfy hot ratio + } + return hotCountThreshold; + } + } + // should not be here + return 100; +} + +bool MplProfileData::IsHotCallSite(uint64_t freq) { + auto &h = summary.GetHistogram(); + if (hotCountThreshold == 0) { + if (Options::profileHotCountSeted) { + hotCountThreshold = Options::profileHotCount; + } else if (summary.GetTotalCount() > 0 && !h.empty() && h[0].countRatio == 0) { + // init countRatio and compute hotCountThreshold + summary.ProcessHistogram(); + hotCountThreshold = GetHotThreshold(); + } else if (h.empty()) { + // should not be here + ASSERT(0, "should not be here"); + hotCountThreshold = 1; + } + } + return freq >= hotCountThreshold; +} + +} // namespace maple diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index 8e0411bb22..c333420826 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace namemangler { #ifdef __MRT_DEBUG @@ -585,13 +586,111 @@ size_t GetSleb128Size(int32_t v) { int end = ((v >= 0) ? 0 : -1); while (hasMore) { - // judege whether has More valid rem - hasMore = (rem != end) || - ((static_cast(rem) & 1) != (static_cast((static_cast(v) >> 6)) & 1)); + // judege whether has more valid rem + hasMore = (rem != end) || ((static_cast(rem) & 1) != + (static_cast((static_cast(v) >> 6)) & 1)); size++; v = rem; rem >>= static_cast(kGreybackOffset); // intended signed shift: block codedex here } return size; } + +// encode signed to output stream +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { + bool more; + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + value >>= kGreybackOffset; + more = !((((value == 0) && ((byte & 0x40) == 0)) || + ((value == -1) && ((byte & 0x40) != 0)))); + count++; + if (more) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << static_cast(byte); + } while (more); + return count; +} + +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + value >>= kGreybackOffset; + count++; + if (value != 0) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << char(byte); + } while (value != 0); + return count; +} + +// decode a ULEB128 value. +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + uint64_t value = 0; + unsigned shift = 0; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + uint64_t slice = *p & 0x7f; + if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value += slice << shift; + shift += kGreybackOffset; + } while (*p++ >= 128); + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + +// decode a SLEB128 value. +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + int64_t value = 0; + unsigned shift = 0; + uint8_t byte; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + byte = *p; + uint64_t slice = byte & 0x7f; + if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || + (shift == 63 && slice != 0 && slice != 0x7f)) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value |= slice << shift; + shift += kGreybackOffset; + ++p; + } while (byte >= 128); + // Sign extend negative numbers if needed. + if (shift < 64 && (byte & 0x40)) { + value |= (-1LL) << shift; + } + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + } // namespace namemangler diff --git a/src/mapleall/mpl2mpl/BUILD.gn b/src/mapleall/mpl2mpl/BUILD.gn index c41431ec49..63ba35bebe 100755 --- a/src/mapleall/mpl2mpl/BUILD.gn +++ b/src/mapleall/mpl2mpl/BUILD.gn @@ -57,7 +57,7 @@ src_libmpl2mpl = [ "src/inline_analyzer.cpp", "src/inline_transformer.cpp", "src/method_replace.cpp", - "src/gcov_parser.cpp", + "src/mpl_profdata_parser.cpp", ] configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] diff --git a/src/mapleall/mpl2mpl/include/gcov_parser.h b/src/mapleall/mpl2mpl/include/gcov_parser.h deleted file mode 100644 index 85dcb3566d..0000000000 --- a/src/mapleall/mpl2mpl/include/gcov_parser.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. - * - * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. - * You can use this software according to the terms and conditions of the MulanPSL - 2.0. - * You may obtain a copy of MulanPSL - 2.0 at: - * - * https://opensource.org/licenses/MulanPSL-2.0 - * - * 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 MulanPSL - 2.0 for more details. - */ - -#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#include "mempool.h" -#include "mempool_allocator.h" -#include "bb.h" -#include "maple_phase_manager.h" -#include "gcov_profile.h" - -namespace maple { -using gcov_position_t = unsigned; -// counter defined in gcov-counter.def -enum { - GCOV_COUNTER_ARCS, - GCOV_COUNTER_V_INTERVAL, - GCOV_COUNTER_V_POW2, - GCOV_COUNTER_V_SINGLE, - GCOV_COUNTER_V_INDIR, - GCOV_COUNTER_AVERAGE, - GCOV_COUNTER_IOR, - GCOV_TIME_PROFILER, - GCOV_COUNTER_ICALL_TOPNV, - GCOV_COUNTERS -}; - -class GcovVar { - public: - GcovVar() { - file = nullptr; - buffer = nullptr; - } - FILE *file = nullptr; - gcov_position_t start = 0; - unsigned offset = 0; - unsigned length = 0; - unsigned overread = 0; - int error = 0; - int mode = 0; - int endian = 0; - size_t alloc = 0; - gcov_unsigned_t* buffer = nullptr; -}; - -class MGcovParser : public AnalysisResult { - public: - MGcovParser(MIRModule &mirmod, MemPool *memPool, bool debug) : AnalysisResult(memPool), m(mirmod), - alloc(memPool), localMP(memPool), gcovData(nullptr), dumpDetail(debug) { - gcovVar = localMP->New(); - } - ~MGcovParser() override { - localMP = nullptr; - gcovData = nullptr; - gcovVar = nullptr; - } - int ReadGcdaFile(); - void DumpFuncInfo(); - GcovProfileData *GetGcovData() { return gcovData; } - - private: - using gcov_bucket_type = struct { - gcov_unsigned_t num_counters; - gcov_type min_value; - gcov_type cum_value; - }; - - struct gcov_ctr_summary { - gcov_unsigned_t num; - gcov_unsigned_t runs; - gcov_type sum_all; - gcov_type run_max; - gcov_type sum_max; - gcov_bucket_type histogram[252]; - }; - struct gcov_summary { - gcov_unsigned_t checksum; - struct gcov_ctr_summary ctrs[GCOV_COUNTER_V_INTERVAL]; - }; - - int GcovReadMagic(gcov_unsigned_t magic, gcov_unsigned_t expected); - int GcovOpenFile(const char *name, int mode); - gcov_unsigned_t from_file(gcov_unsigned_t value); - const gcov_unsigned_t *GcovReadWords(unsigned words); - void GcovSync(gcov_position_t base, gcov_unsigned_t length); - int GcovCloseFile(void); - void GcovAllocate(unsigned length); - gcov_unsigned_t GcovReadUnsigned(void); - gcov_position_t GcovGetPosition(void); - gcov_type GcovReadCounter(void); - void GcovReadSummary(struct gcov_summary *summary); - - MIRModule &m; - MapleAllocator alloc; - MemPool *localMP; - GcovProfileData *gcovData; - GcovVar *gcovVar = nullptr; - bool dumpDetail; -}; - -MAPLE_MODULE_PHASE_DECLARE(M2MGcovParser) - -} // end of namespace maple - -#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/include/inline_transformer.h b/src/mapleall/mpl2mpl/include/inline_transformer.h index 8d95a97381..78137411b9 100644 --- a/src/mapleall/mpl2mpl/include/inline_transformer.h +++ b/src/mapleall/mpl2mpl/include/inline_transformer.h @@ -55,7 +55,9 @@ class InlineTransformer { callee(callee), callStmt(callStmt), dumpDetail(dumpDetail), - cg(cg) {} + cg(cg), + updateFreq(Options::profileUse && caller.GetFuncProfData() && callee.GetFuncProfData()){}; + bool PerformInline(BlockNode &enclosingBlk); static void ReplaceSymbols(BaseNode*, uint32, const std::vector*); static void ConvertPStaticToFStatic(MIRFunction &func); @@ -91,6 +93,7 @@ class InlineTransformer { LabelIdx returnLabelIdx = 0; // The lableidx where the code will jump when the callee returns. StmtNode *labelStmt = nullptr; // The LabelNode we created for the callee, if needed. CallGraph *cg = nullptr; + bool updateFreq = false; }; } // namespace maple #endif // MPL2MPL_INCLUDE_INLINE_TRANSFORMER_H diff --git a/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h new file mode 100644 index 0000000000..1a83fa5c83 --- /dev/null +++ b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#include "bb.h" +#include "maple_phase_manager.h" +#include "mempool.h" +#include "mempool_allocator.h" +#include "mpl_profdata.h" + +namespace maple { +// maple profile data format +// Summary layout +// MagicNumber +// chesum +// run times +// counts number +// count Maxium value +// accumulated count sum +// cout histogram size (count statistic information used for hot function check) +// count lower bound <-- begin of histogram details +// countNum in current range +// minium value in count range +// accumulated count sum +// count range <-- another histogram element +// countNum +// minium value in cout range +// accumulated count sum +// Function profile layout (now only including edge profiling counts) +// function numbers +// function Ident (key number to identify each function(now use mirfunction->puidx) +// function line number checksum +// function cfg checksum +// counts number in function 0 +// count <-- begin of count value +// count +// counts number in function 1 +// count +// ... +// now only unsigned number in profile data, use ULEB128 to encode/decode value for file size + +const uint32_t kMapleProfDataMagicNumber = 0xA0EFEF; + +class ProfDataBinaryImportBase { + public: + ProfDataBinaryImportBase(std::string &filename, std::ifstream &input) : fileName(filename), inputStream(input) {} + template + T ReadNum(); + std::ifstream &GetInputStream() { + return inputStream; + } + std::string &GetProfDataFileName() { + return fileName; + } + void SetPosition(uint8_t *p) { + pos = p; + } + uint8_t *GetPosition() { + return pos; + } + + private: + std::string &fileName; + std::ifstream &inputStream; + uint8_t *pos = nullptr; +}; + +class ProfileSummaryImport : public ProfDataBinaryImportBase { + public: + ProfileSummaryImport(std::string &outputFile, std::ifstream &input) : ProfDataBinaryImportBase(outputFile, input) {} + int ReadSummary(MplProfileData*); + + private: + void ReadMProfMagic(); +}; + +class FunctionProfileImport : public ProfDataBinaryImportBase { + public: + FunctionProfileImport(std::string &inputFile, std::ifstream &input) : ProfDataBinaryImportBase(inputFile, input) {} + int ReadFuncProfile(MplProfileData *profData); +}; + +class MplProfDataParser : public AnalysisResult { + public: + MplProfDataParser(MIRModule &mirmod, MemPool *mp, bool debug) + : AnalysisResult(mp), m(mirmod), alloc(memPool), mempool(mp), dumpDetail(debug) {} + ~MplProfDataParser() = default; + MplProfileData *GetProfData() { + return profData; + } + int ReadMapleProfileData(); + + private: + MIRModule &m; + MapleAllocator alloc; + MemPool *mempool; + MplProfileData *profData = nullptr; + bool dumpDetail = false; +}; + +MAPLE_MODULE_PHASE_DECLARE(MMplProfDataParser) + +} // end of namespace maple + +#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/src/call_graph.cpp b/src/mapleall/mpl2mpl/src/call_graph.cpp index 449da87d5c..6dd6a88cab 100644 --- a/src/mapleall/mpl2mpl/src/call_graph.cpp +++ b/src/mapleall/mpl2mpl/src/call_graph.cpp @@ -14,7 +14,6 @@ */ #include "call_graph.h" - #include "option.h" #include "retype.h" #include "string_utils.h" @@ -190,7 +189,7 @@ bool CGNode::IsCalleeOf(CGNode *func) const { } uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo->stmtFreqs.count(callstmt->GetStmtID()) > 0) { return funcInfo->stmtFreqs[callstmt->GetStmtID()]; } @@ -199,9 +198,9 @@ uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { } uint64_t CGNode::GetFuncFrequency() const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo) { - return funcInfo->GetFuncFrequency(); + return funcInfo->GetFuncRealFrequency(); } ASSERT(0, "should not be here"); return 0; @@ -257,8 +256,8 @@ void CallGraph::DelNode(CGNode &node) { } } -CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, - const KlassHierarchy &kh, const std::string &fn) +CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, const KlassHierarchy &kh, + const std::string &fn) : AnalysisResult(&memPool), mirModule(&m), cgAlloc(&memPool), @@ -524,7 +523,7 @@ void CallGraph::RecordLocalConstValue(const StmtNode *stmt) { CallNode *CallGraph::ReplaceIcallToCall(BlockNode &body, IcallNode *icall, PUIdx newPUIdx) { MapleVector opnds(icall->GetNopnd().begin() + 1, icall->GetNopnd().end(), - CurFunction()->GetCodeMPAllocator().Adapter()); + CurFunction()->GetCodeMPAllocator().Adapter()); CallNode *newCall = nullptr; if (icall->GetOpCode() == OP_icall) { newCall = mirBuilder->CreateStmtCall(newPUIdx, opnds, OP_call); @@ -747,8 +746,8 @@ void CallGraph::HandleICall(BlockNode &body, CGNode &node, StmtNode *stmt, uint3 icallToFix.insert({funcType->GetTypeIndex(), tempSet}); } CHECK_FATAL(CurFunction()->GetPuidx() == node.GetPuIdx(), "Error"); - Callsite callSite = { callInfo, node.GetCallee().at(callInfo) }; - icallToFix.at(funcType->GetTypeIndex())->insert({ node.GetPuIdx(), callSite }); + Callsite callSite = {callInfo, node.GetCallee().at(callInfo)}; + icallToFix.at(funcType->GetTypeIndex())->insert({node.GetPuIdx(), callSite}); } void CallGraph::HandleBody(MIRFunction &func, BlockNode &body, CGNode &node, uint32 loopDepth) { @@ -1235,7 +1234,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { Opcode op = stmt->GetOpCode(); switch (op) { case OP_comment: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_brtrue: case OP_brfalse: case OP_try: @@ -1504,7 +1503,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { } } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_call: case OP_callassigned: { CallNode *callNode = static_cast(stmt); @@ -1559,8 +1558,9 @@ void IPODevirtulize::DevirtualFinal() { if (GlobalTables::GetGsymTable().GetSymbolFromStrIdx(classType->GetStaticFieldsGStrIdx(i)) == nullptr) { continue; } - TyIdx tyIdx = GlobalTables::GetGsymTable().GetSymbolFromStrIdx( - classType->GetStaticFieldsPair(i).first)->GetInferredTyIdx(); + TyIdx tyIdx = GlobalTables::GetGsymTable() + .GetSymbolFromStrIdx(classType->GetStaticFieldsPair(i).first) + ->GetInferredTyIdx(); if (tyIdx != kInitTyIdx && tyIdx != kNoneTyIdx) { CHECK_FATAL(attribute.GetAttr(FLDATTR_final), "Must be final private"); if (debugFlag) { @@ -1744,13 +1744,13 @@ void CallGraph::RemoveFileStaticRootNodes() { std::vector staticRoots; std::copy_if(rootNodes.begin(), rootNodes.end(), std::inserter(staticRoots, staticRoots.begin()), [](const CGNode *root) { - // root means no caller, we should also make sure that root is not be used in addroffunc - auto mirFunc = root->GetMIRFunction(); - return root != nullptr && mirFunc != nullptr && // remove before - // if static functions or inline but not extern modified functions are not used anymore, - // they can be removed safely. - !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); - }); + // root means no caller, we should also make sure that root is not be used in addroffunc + auto mirFunc = root->GetMIRFunction(); + return root != nullptr && mirFunc != nullptr && // remove before + // if static functions or inline but not extern modified functions are not used anymore, + // they can be removed safely. + !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); + }); for (auto *root : staticRoots) { // DFS delete root and its callee that is static and have no caller after root is deleted DelNode(*root); diff --git a/src/mapleall/mpl2mpl/src/gen_profile.cpp b/src/mapleall/mpl2mpl/src/gen_profile.cpp index 2f1a0bdb0e..cff72a9561 100644 --- a/src/mapleall/mpl2mpl/src/gen_profile.cpp +++ b/src/mapleall/mpl2mpl/src/gen_profile.cpp @@ -104,9 +104,9 @@ void ProfileGen::CreateModProfDesc() { modProfDescSymMirConst->AddItem(checksumMirConst, 5); // Make the profile file name as fileName.gcda - std::string profFileName = mod.GetProfileDataFileName(); + std::string profFileName = mod.GetProfileDataFileName() + namemangler::kProfFileNameExt; auto *profileFNMirConst = - modMP->New("./" + profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); + modMP->New(profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); modProfDescSymMirConst->AddItem(profileFNMirConst, 6); // Additional profiling (in addition to frequency profiling) should be added here diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index 65b2c8d8a9..e0d6984461 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -92,7 +92,7 @@ void MInline::InitParams() { } void MInline::InitProfile() const { - // gcov use different profile data, return + // maple profile use different profile data, return if (Options::profileUse) { return; } @@ -117,7 +117,7 @@ void MInline::InitRCWhiteList() { void MInline::InitExcludedCaller() { std::set specialfunc = { - std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), + std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), }; for (auto it = specialfunc.begin(); it != specialfunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -140,27 +140,40 @@ void MInline::InitExcludedCallee() { (void)excludedCallee.insert(strIdx); } std::set setArrayHotFunc = { - std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_2FObject_3B_29Ljava_2Flang_2FString_3B"), - std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_29Ljava_2Flang_2FObject_3B"), + std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_" + "2FObject_3B_29Ljava_2Flang_2FString_3B"), + std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_" + "2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_" + "29Ljava_2Flang_2FObject_3B"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7Crun_7C_28_29V"), - std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), + std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_" + "7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), std::string("Landroid_2Fview_2Fanimation_2FTransformation_3B_7C_3Cinit_3E_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartOtherServices_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FSettings_3B_7CreadLPw_7C_28Ljava_2Futil_2FList_3B_29Z"), std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CupdateOomAdjLocked_7C_28_29V"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), - std::string("Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_" + "2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), + std::string( + "Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartBootstrapServices_7C_28_29V"), std::string("Ljava_2Flang_2FThrowable_3B_7CgetOurStackTrace_7C_28_29ALjava_2Flang_2FStackTraceElement_3B"), std::string("Ldalvik_2Fsystem_2FVMStack_3B_7CgetStackClass2_7C_28_29Ljava_2Flang_2FClass_3B"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_2Fapp_2FIApplicationThread_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_2FResultReceiver_3B_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_" + "2Fapp_2FIApplicationThread_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_" + "2FResultReceiver_3B_29Z"), }; for (auto it = setArrayHotFunc.begin(); it != setArrayHotFunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -251,7 +264,7 @@ FuncCostResultType MInline::GetFuncCost(const MIRFunction &func, const BaseNode break; } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_customcallassigned: case OP_polymorphiccallassigned: case OP_customcall: @@ -421,17 +434,19 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee LogInfo::MapleLogger() << "[CHECK_HOT] " << callee.GetName() << " to " << caller.GetName() << " op " << callStmt.GetOpCode() << '\n'; } - // use gcov profile + // use maple instrument profile if (Options::profileUse) { - return caller.GetFuncProfData()->IsHotCallSite(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) return false; + int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + ASSERT(freq > 0, "sanity check"); + return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); } return module.GetProfile().CheckFuncHot(caller.GetName()); } bool MInline::FuncInlinable(const MIRFunction &func) const { std::string name = func.GetName(); - if (StringUtils::StartsWith(name, kReflectionClassStr) || - StringUtils::StartsWith(name, kJavaLangClassesStr) || + if (StringUtils::StartsWith(name, kReflectionClassStr) || StringUtils::StartsWith(name, kJavaLangClassesStr) || StringUtils::StartsWith(name, kJavaLangReferenceStr)) { return false; } @@ -686,7 +701,7 @@ static InlineResult GetInlineResult(uint32 threshold, uint32 thresholdType, uint } void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction &callee, const CallNode &callStmt, - uint32 &threshold, uint32 &thresholdType) { + uint32 &threshold, uint32 &thresholdType) { // Update threshold if this callsite is hot, or dealing with recursive function if (inlineWithProfile && IsHotCallSite(caller, callee, callStmt)) { threshold = hotFuncThreshold; @@ -705,9 +720,7 @@ void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction threshold <<= kRelaxThresholdForInlineHint; } // We don't always inline called_once callee to avoid super big caller - if (module.GetSrcLang() == kSrcLangC && - callee.GetAttr(FUNCATTR_called_once) && - callee.GetAttr(FUNCATTR_static)) { + if (module.GetSrcLang() == kSrcLangC && callee.GetAttr(FUNCATTR_called_once) && callee.GetAttr(FUNCATTR_static)) { threshold <<= kRelaxThresholdForCalledOnce; } } diff --git a/src/mapleall/mpl2mpl/src/inline_transformer.cpp b/src/mapleall/mpl2mpl/src/inline_transformer.cpp index d387f64d29..67a3abc455 100644 --- a/src/mapleall/mpl2mpl/src/inline_transformer.cpp +++ b/src/mapleall/mpl2mpl/src/inline_transformer.cpp @@ -307,7 +307,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s dStmt = builder.CreateStmtRegassign(mirPreg->GetPrimType(), pregIdx, currBaseNode); } dStmt->SetSrcPos(stmt.GetSrcPos()); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(dStmt->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); @@ -315,7 +315,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s newBody.ReplaceStmt1WithStmt2(&stmt, dStmt); newBody.InsertAfter(dStmt, gotoNode); } else { - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); } @@ -458,10 +458,9 @@ BlockNode *InlineTransformer::CloneFuncBody(BlockNode &funcBody, bool recursiveF if (callee.IsFromMpltInline()) { return funcBody.CloneTree(theMIRModule->GetCurFuncCodeMPAllocator()); } - if (Options::profileUse) { + if (updateFreq) { auto *callerProfData = caller.GetFuncProfData(); auto *calleeProfData = callee.GetFuncProfData(); - ASSERT(callerProfData && calleeProfData, "nullptr check"); uint64_t callsiteFreq = callerProfData->GetStmtFreq(callStmt.GetStmtID()); uint64_t calleeEntryFreq = calleeProfData->GetFuncFrequency(); uint32_t updateOp = (kKeepOrigFreq | kUpdateFreqbyScale); @@ -562,7 +561,7 @@ void InlineTransformer::AssignActualsToFormals(BlockNode &newBody, uint32 stIdxO CHECK_NULL_FATAL(currBaseNode); CHECK_NULL_FATAL(formal); AssignActualToFormal(newBody, stIdxOff, regIdxOff, *currBaseNode, *formal); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(newBody.GetFirst()->GetStmtID(), callStmt.GetStmtID()); } } @@ -606,7 +605,7 @@ void InlineTransformer::HandleReturn(BlockNode &newBody) { } } } - if (Options::profileUse && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { + if (updateFreq && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } @@ -623,7 +622,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne beginCmt += callee.GetName(); StmtNode *commNode = builder.CreateStmtComment(beginCmt.c_str()); enclosingBlk.InsertBefore(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } // end inlining function @@ -639,7 +638,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne } commNode = builder.CreateStmtComment(endCmt.c_str()); enclosingBlk.InsertAfter(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } CHECK_FATAL(callStmt.GetNext() != nullptr, "null ptr check"); @@ -663,7 +662,7 @@ void InlineTransformer::GenReturnLabel(BlockNode &newBody, uint32 inlinedTimes) // record the created label labelStmt = builder.CreateStmtLabel(returnLabelIdx); newBody.AddStatement(labelStmt); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } diff --git a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp index 375fba0b8d..ff39484443 100644 --- a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp +++ b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp @@ -16,7 +16,7 @@ #include "me_phase_manager.h" #include "ipa_phase_manager.h" #include "ipa_side_effect.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -109,7 +109,7 @@ MAPLE_ANALYSIS_PHASE_REGISTER(M2MCallGraph, callgraph) MAPLE_ANALYSIS_PHASE_REGISTER(M2MKlassHierarchy, classhierarchy) MAPLE_ANALYSIS_PHASE_REGISTER(M2MAnnotationAnalysis, annotationanalysis) MAPLE_ANALYSIS_PHASE_REGISTER(ProfileGenPM, ProfileGenPM) -MAPLE_ANALYSIS_PHASE_REGISTER(M2MGcovParser, gcovparser) +MAPLE_ANALYSIS_PHASE_REGISTER(MMplProfDataParser, grofDataParser) MAPLE_TRANSFORM_PHASE_REGISTER(M2MInline, inline) MAPLE_TRANSFORM_PHASE_REGISTER(M2MIPODevirtualize, ipodevirtulize) diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp new file mode 100644 index 0000000000..95bd0febdd --- /dev/null +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#include "mpl_profdata_parser.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { + +template +T ProfDataBinaryImportBase::ReadNum() { + unsigned numBytesRead = 0; + uint64_t val = namemangler::DecodeULEB128(pos, &numBytesRead); + + pos += numBytesRead; + return static_cast(val); +} + +int ProfileSummaryImport::ReadSummary(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint64_t magicNum = ReadNum(); + if (magicNum != kMapleProfDataMagicNumber) { + LogInfo::MapleLogger() << "magic number error, quit\n"; + return 1; + } + uint64_t checksum = ReadNum(); + uint32_t runtimes = ReadNum(); + uint32_t numofCounts = ReadNum(); + uint64_t maxCount = ReadNum(); + uint64_t sumCount = ReadNum(); + profData->summary.SetSummary(checksum, runtimes, numofCounts, maxCount, sumCount); + uint32_t veclen = ReadNum(); + + for (uint32_t i = 0; i < veclen; i++) { + uint32_t r1 = ReadNum(); + uint32_t r2 = ReadNum(); + uint64_t r3 = ReadNum(); + uint64_t r4 = ReadNum(); + profData->summary.AddHistogramRecord(r1, r2, r3, r4); + } + + return 0; +} + +int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint32_t funcNums = ReadNum(); + if (funcNums == 0) { + return 1; + } + + for (uint32_t i = 0; i < funcNums; i++) { + uint32_t funcIdent = ReadNum(); + uint32_t linocheckSum = ReadNum(); + uint32_t cfgcheckSum = ReadNum(); + uint32_t countNum = ReadNum(); + FuncProfInfo *funcProf = profData->AddNewFuncProfile(funcIdent, linocheckSum, cfgcheckSum, countNum); + CHECK_FATAL(funcProf != nullptr, "nullptr check"); + funcProf->counts.resize(countNum); + for (uint32_t j = 0; j < countNum; j++) { + funcProf->counts[j] = ReadNum(); + } + } + return 0; +} + +int MplProfDataParser::ReadMapleProfileData() { + std::string mprofDataFile = Options::profile; + if (mprofDataFile.empty()) { + if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { + mprofDataFile.append(env_gcovprefix); + if (mprofDataFile.back() != '/') { + mprofDataFile.append("/"); + } + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; + } + uint32_t stripnum = 0; + if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(env_gcovprefixstrip); + stripnum = std::stoi(strip); + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; + } + } + std::string profDataFileName = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "module profdata Name: " << profDataFileName << std::endl; + } + // reduce path in profDataFileName + while (stripnum > 0 && profDataFileName.size() > 1) { + size_t pos = profDataFileName.find_first_of("/", 1); + if (pos == std::string::npos) { + break; + } + profDataFileName = profDataFileName.substr(pos); + stripnum--; + } + if (dumpDetail) { + LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; + } + CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); + mprofDataFile.append(profDataFileName); + } else { + // if gcov_prefix is not set, find .mprofdata according to m.profiledata + mprofDataFile = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "NO ENV, module profdata Name: " << mprofDataFile << std::endl; + } + } + // add .mprofdata + mprofDataFile.append(namemangler::kMplProfFileNameExt); + } + ASSERT(!mprofDataFile.empty(), "null check"); + if (dumpDetail) { + LogInfo::MapleLogger() << "will open mprofileData " << mprofDataFile << std::endl; + } + // create mpl profdata + profData = mempool->New(mempool, &alloc); + // read .mprofdata + std::ifstream inputStream(mprofDataFile, (std::ios::in | std::ios::binary)); + if (!inputStream) { + LogInfo::MapleLogger() << "Could not open the file " << mprofDataFile << "\n"; + return 1; + } + // get length of file + inputStream.seekg(0, std::ios::end); + uint32_t length = inputStream.tellg(); + inputStream.seekg(0, std::ios::beg); + const uint32_t sizeThreshold = 1024 * 10; + CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); + + std::unique_ptr buffer = std::make_unique(length); + inputStream.read(buffer.get(), length); + inputStream.close(); + // read 1st part summary + ProfileSummaryImport summaryImport(mprofDataFile, inputStream); + summaryImport.SetPosition((uint8_t*)(buffer.get())); + int res = summaryImport.ReadSummary(profData); + if (res) { + LogInfo::MapleLogger() << "no summary part\n"; + return 1; + } + if (dumpDetail) { + profData->summary.DumpSummary(); + } + // read 2nd part function profile data + FunctionProfileImport funcImport(mprofDataFile, inputStream); + funcImport.SetPosition(summaryImport.GetPosition()); + res = funcImport.ReadFuncProfile(profData); + if (res) { + LogInfo::MapleLogger() << "no function profile part\n"; + return 1; + } + if (dumpDetail) { + profData->DumpFunctionsProfile(); + } + return 0; +} + +void MMplProfDataParser::GetAnalysisDependence(AnalysisDep &aDep) const { + aDep.SetPreservedAll(); +} + +bool MMplProfDataParser::PhaseRun(maple::MIRModule &m) { + MemPool *memPool = m.GetMemPool(); // use global pool to store profile data + bool enableDebug = true; // true to dump trace + MplProfDataParser parser(m, memPool, enableDebug); + int res = parser.ReadMapleProfileData(); + if (res) { + // something wrong + LogInfo::MapleLogger() << " parse .mprofdata error\n"; + return false; + } + m.SetMapleProfile(parser.GetProfData()); + + return true; +} + +} // end namespace maple -- Gitee From 88e4496a26158e1d87c23fc5842d80408e891984 Mon Sep 17 00:00:00 2001 From: fye Date: Thu, 11 Aug 2022 08:57:58 -0700 Subject: [PATCH 4/7] profuse: ~170+~60+2 fixes for warnings from CI tools --- src/mapleall/maple_ir/include/mir_module.h | 10 +-- .../maple_me/include/me_loop_unrolling.h | 3 +- src/mapleall/maple_me/src/bb.cpp | 26 +++--- src/mapleall/maple_me/src/hdse.cpp | 11 +-- src/mapleall/maple_me/src/me_cfg.cpp | 50 +++++------ src/mapleall/maple_me/src/me_loop_canon.cpp | 67 +++++++-------- .../maple_me/src/me_loop_inversion.cpp | 4 +- src/mapleall/maple_me/src/me_profile_use.cpp | 4 +- .../maple_me/src/me_value_range_prop.cpp | 83 ++++++++++--------- src/mapleall/maple_me/src/optimizeCFG.cpp | 17 ++-- src/mapleall/maple_util/include/namemangler.h | 2 +- src/mapleall/maple_util/src/mpl_profdata.cpp | 19 +++-- src/mapleall/maple_util/src/namemangler.cpp | 44 +++++----- src/mapleall/mpl2mpl/src/inline.cpp | 6 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 26 +++--- 15 files changed, 190 insertions(+), 182 deletions(-) diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index f5965f008d..700b022338 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -342,12 +342,12 @@ class MIRModule { std::string GetProfileDataFileName() const { std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); - char *gcov_path = std::getenv("GCOV_PREFIX"); - std::string gcov_prefix = gcov_path ? gcov_path : ""; - if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { - gcov_prefix.append("/"); + const char *gcovPath = std::getenv("GCOV_PREFIX"); + std::string gcovPrefix = gcovPath ? gcovPath : ""; + if (!gcovPrefix.empty() && (gcovPrefix.back() != '/')) { + gcovPrefix.append("/"); } - profileDataFileName = gcov_prefix + profileDataFileName; + profileDataFileName = gcovPrefix + profileDataFileName; return profileDataFileName; } diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 1e5f57be8f..fe36d56e73 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -29,8 +29,7 @@ constexpr uint32 kMaxCost = 100; constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll - { + enum ReturnKindOfFullyUnroll { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 290a3c6caa..1096c836d9 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,9 +13,6 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" - -#include - #include "me_ir.h" #include "me_ssa.h" #include "mempool_allocator.h" @@ -83,7 +80,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse && frequency >= 0) { + // if (Options::profileUse && frequency >= 0) { + if (Options::profileUse) { mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; @@ -487,21 +485,19 @@ void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - int diff = abs(succFreqs - GetFrequency()); - if (len == 0 || diff <= 1) return; - int64_t scaledSum = 0; - for (int i = 0; i < len; i++) { - int64_t sfreq = GetSuccFreq()[i]; + int diff = static_cast(abs(succFreqs - GetFrequency())); + if (len == 0 || diff <= 1) {return;} + for (uint32 i = 0; i < len; i++) { + int64_t sfreq = GetSuccFreq()[static_cast(i)]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); - scaledSum += scalefreq; - SetSuccFreq(i, scalefreq); + SetSuccFreq(static_cast(i), scalefreq); // update succ frequency with new difference if needed if (updateBBFreqOfSucc) { - auto *succ = GetSucc(i); - int64_t diff = scalefreq - sfreq; - int64_t succBBnewFreq = succ->GetFrequency() + diff; + auto *succBBLoc = GetSucc(static_cast(i)); + int64_t diffFreq = scalefreq - sfreq; + int64_t succBBnewFreq = succBBLoc->GetFrequency() + diffFreq; if (succBBnewFreq >= 0) { - succ->SetFrequency(succBBnewFreq); + succBBLoc->SetFrequency(static_cast(succBBnewFreq)); } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 99748916e6..52c7360992 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -250,11 +250,12 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } bb.SetKind(kBBFallthru); if (UpdateFreq()) { - int64_t succ0Freq = bb.GetSuccFreq()[0]; + int64_t succ0Freq = static_cast(bb.GetSuccFreq()[0]); bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + + (bb.GetFrequency() - succ0Freq))); } } // A ivar contained in stmt @@ -289,7 +290,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().back(); + removedFreq = static_cast(bb.GetSuccFreq().back()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -302,7 +303,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // change to unconditional branch BB *succbb = bb.GetSucc().front(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().front(); + removedFreq = static_cast(bb.GetSuccFreq().front()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -316,7 +317,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { if (UpdateFreq()) { bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + removedFreq)); } } else { DetermineUseCounts(condbr->GetOpnd()); diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index 3b9a752fde..8719578fea 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -1970,9 +1970,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { for (auto *pred : bb->GetPred()) { int idx = pred->GetSuccIndex(*bb); ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); - inputFreq += pred->GetSuccFreq()[idx]; + inputFreq += static_cast(pred->GetSuccFreq()[static_cast(idx)]); } - bb->SetFrequency(inputFreq); + bb->SetFrequency(static_cast(inputFreq)); } // make bb frequency and succs frequency consistent bb->UpdateEdgeFreqs(false); @@ -1984,9 +1984,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { void MeCFG::ClearFuncFreqInfo() { SetUpdateCFGFreq(false); func.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; + auto &bbVecLoc = GetAllBBs(); + for (size_t i = 0; i < bbVecLoc.size(); ++i) { // skip common entry and common exit + auto *bb = bbVecLoc[i]; if (bb == nullptr) { continue; } @@ -1997,7 +1997,7 @@ void MeCFG::ClearFuncFreqInfo() { // return value is 0 means pass verification, else has problem int MeCFG::VerifyBBFreq(bool checkFatal) { - int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + int64_t entryFreq = static_cast(func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency()); ASSERT(entryFreq >= 0, "sanity check"); bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit @@ -2031,19 +2031,20 @@ int MeCFG::VerifyBBFreq(bool checkFatal) { for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } - if (succSumFreq != bb->GetFrequency()) { - int diff = succSumFreq - bb->GetFrequency(); - diff = diff >= 0 ? diff : -diff; - if (diff > 1) { - if (checkFatal) { - LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; - LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq - << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); - } else { - ClearFuncFreqInfo(); - return 1; - } + if (succSumFreq == bb->GetFrequency()) { + continue; + } + int64 diff = static_cast(succSumFreq - bb->GetFrequency()); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; } } } @@ -2088,9 +2089,9 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (theCFG->DumpIRProfileFile()) { std::string fileName = "after-mecfgbuild"; if (f.IsPme()) { - fileName.append("-lfo"); + static_cast(fileName.append("-lfo")); } else { - fileName.append("-mplme"); + static_cast(fileName.append("-mplme")); } theCFG->DumpToFile(fileName, false, true); } @@ -2101,13 +2102,14 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { // if transform pass is not fully support, set disableFreqInfo to true // function profile information will be deleted after verification phase - bool disableFreqInfo = false; if (f.GetCfg()->UpdateCFGFreq()) { - f.GetCfg()->VerifyBBFreq(); + static_cast(f.GetCfg()->VerifyBBFreq()); } - if (!disableFreqInfo) return false; +#ifdef disableFreqInfo + //if (!disableFreqInfo) {return falsea}; // clear function profile information f.GetCfg()->ClearFuncFreqInfo(); +#endif return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 05c4b15f8e..e3f4c6e15d 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -100,8 +100,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - uint64_t freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(freq); + uint64_t freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(freq)); mergedBB->PushBackSuccFreq(freq); } splittedBB->ReplacePred(pred, mergedBB); @@ -134,8 +134,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(mergedBB->GetFrequency() + freq)); } pred->ReplaceSucc(splittedBB, mergedBB); if (updateFreqs) { @@ -254,38 +254,39 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { if (loop.Has(*succ)) { inLoopBBs.push(succ); traveledBBs.insert(succ); - } else { - bool needNewExitBB = false; - for (auto pred : succ->GetPred()) { - if (!loop.Has(*pred)) { - needNewExitBB = true; - break; - } + continue; + } + bool needNewExitBB = false; + for (auto pred : succ->GetPred()) { + if (!loop.Has(*pred)) { + needNewExitBB = true; + break; + } + } + if (needNewExitBB) { + // break the critical edge for code sinking + BB *newExitBB = cfg->NewBasicBlock(); + newExitBB->SetKind(kBBFallthru); + auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + ASSERT(idx >= 0 && idx < curBB->GetSuccFreq().size(), "sanity check"); + freq = curBB->GetSuccFreq()[static_cast(idx)]; + } + curBB->ReplaceSucc(succ, newExitBB); + succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(static_cast(freq)); + newExitBB->PushBackSuccFreq(freq); } - if (needNewExitBB) { - // break the critical edge for code sinking - BB *newExitBB = cfg->NewBasicBlock(); - newExitBB->SetKind(kBBFallthru); - auto pos = succ->GetPredIndex(*curBB); - uint64_t freq = 0; - if (updateFreqs) { - int idx = curBB->GetSuccIndex(*succ); - freq = curBB->GetSuccFreq()[idx]; - } - curBB->ReplaceSucc(succ, newExitBB); - succ->AddPred(*newExitBB, pos); - if (updateFreqs) { - newExitBB->SetFrequency(freq); - newExitBB->PushBackSuccFreq(freq); - } - if (!curBB->GetMeStmts().empty()) { - UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); - } - succ = newExitBB; - isCFGChange = true; + if (!curBB->GetMeStmts().empty()) { + UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } - loop.InsertInloopBB2exitBBs(*curBB, *succ); + succ = newExitBB; + isCFGChange = true; } + loop.InsertInloopBB2exitBBs(*curBB, *succ); } } } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index d3f9505fed..4bef6afb01 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -204,7 +204,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMap exitbb is set 0 // latchBB fallthru is loop exit - int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(0)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(0, bb.GetFrequency()); bb.SetSuccFreq(1, 0); @@ -219,7 +219,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is loop exit, edge frequency of bb ->exitbb is set 0 // latchBB fallthru is in loop - int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(1)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(1, bb.GetFrequency()); bb.SetSuccFreq(0, 0); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 0041c51b0d..6d510e4451 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -372,8 +372,8 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { if (Options::profileUse) { result = profUse.MapleProfRun(); if (result) { - result = f.GetCfg()->VerifyBBFreq(); - if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + result = f.GetCfg()->VerifyBBFreq() != 0 ? true : false; + if (result && (DEBUGFUNC_NEWPM(f))) { LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; } } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index 19425f68fc..a4d884b1f0 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -3140,14 +3140,14 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB int64_t removedFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { int idx = bb.GetSuccIndex(unreachableBB); - removedFreq = bb.GetSuccFreq()[idx]; + removedFreq = static_cast(bb.GetSuccFreq()[static_cast(idx)]); } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); if (func.GetCfg()->UpdateCFGFreq()) { bb.SetSuccFreq(0, bb.GetFrequency()); - succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + succBB.SetFrequency(static_cast(succBB.GetFrequency() + removedFreq)); unreachableBB.SetFrequency(0); } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); @@ -3522,9 +3522,9 @@ void ValueRangePropagation::RemoveUnreachableBB( condGotoBB.SetKind(kBBFallthru); // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + int64_t removedFreq = static_cast(condGotoBB.GetSuccFreq()[1]); condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + succ0->SetFrequency(static_cast(succ0->GetFrequency() + removedFreq)); } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); @@ -3541,12 +3541,12 @@ void ValueRangePropagation::RemoveUnreachableBB( int64_t removedFreq = 0; // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - removedFreq = condGotoBB.GetSuccFreq()[0]; + removedFreq = static_cast(condGotoBB.GetSuccFreq()[0]); } condGotoBB.RemoveSucc(*succ0); if (func.GetCfg()->UpdateCFGFreq()) { condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + succ1->SetFrequency(static_cast(succ1->GetFrequency() + removedFreq)); } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3707,18 +3707,18 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + exitCopyFallthru->SetFrequency(static_cast(exitCopyFallthru->GetFrequency() + edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } return true; @@ -3756,17 +3756,17 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); if (func.GetCfg()->UpdateCFGFreq()) { - mergeAllFallthruBBs->SetFrequency(edgeFreq); - mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + mergeAllFallthruBBs->SetFrequency(static_cast(edgeFreq)); + mergeAllFallthruBBs->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } mergeAllFallthruBBs->AddSucc(trueBranch); @@ -3829,13 +3829,18 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( BB &pred, BB &bb, BB &trueBranch, ScalarMeExpr *updateSSAExceptTheScalarExpr, std::map> &ssaupdateCandsForCondExpr) { CHECK_FATAL(bb.GetKind() == kBBCondGoto, "must be condgoto bb"); - if (GetRealPredSize(bb) >= kNumOperands) { + if (GetRealPredSize(bb) < kNumOperands) { + CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); + RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); + return true; + } + //if (GetRealPredSize(bb) >= kNumOperands) { if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3843,13 +3848,13 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); // transform may not be consistent with frequency value updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); @@ -3858,7 +3863,7 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3866,14 +3871,14 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - exitCopyFallthru->SetFrequency(edgeFreq); - exitCopyFallthru->PushBackSuccFreq(edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + exitCopyFallthru->SetFrequency(static_cast(edgeFreq)); + exitCopyFallthru->PushBackSuccFreq(static_cast(edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); ASSERT(updatedtrueFreq >= 0, "sanity check"); - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } return true; } @@ -3890,27 +3895,27 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); - newBB->SetFrequency(edgeFreq); - newBB->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + newBB->SetFrequency(static_cast(edgeFreq)); + newBB->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); } - } else { - CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); - RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); - } +// } else { +// CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); +// RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); +// } return true; } diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index abbb818c29..7dd3783949 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -712,8 +712,7 @@ class OptimizeBB { bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization // opportunity for currBB after a/some optimization, we should set it true. // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat - { + enum BBErrStat { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -1761,13 +1760,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { int64_t deletedSuccFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = succ.GetSuccIndex(*rmBB); - deletedSuccFreq = succ.GetSuccFreq()[idx]; + deletedSuccFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); } succ.RemoveSucc(*rmBB, true); if (cfg->UpdateCFGFreq()) { succ.SetSuccFreq(0, succ.GetFrequency()); auto *succofSucc = succ.GetSucc(0); - succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + succofSucc->SetFrequency(static_cast(succofSucc->GetFrequency() + deletedSuccFreq)); } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; @@ -1833,9 +1832,9 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; idx = succ.GetSuccIndex(*affectedBB); ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); - int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + int64_t oldedgeFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); ASSERT(oldedgeFreq >= freq, "sanity check"); - succ.SetSuccFreq(idx, (oldedgeFreq - freq)); + succ.SetSuccFreq(idx, static_cast(oldedgeFreq - freq)); } return true; } @@ -2017,13 +2016,13 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { int64_t removedFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*succ); - removedFreq = pred->GetSuccFreq()[idx]; + removedFreq = static_cast(pred->GetSuccFreq()[static_cast(idx)]); } if (pred->IsPredBB(*newTarget)) { pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*newTarget); - pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + pred->SetSuccFreq(idx, static_cast(pred->GetSuccFreq()[static_cast(idx)] + removedFreq)); } } else { pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later @@ -2032,7 +2031,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (cfg->UpdateCFGFreq()) { int64_t succFreq = succ->GetFrequency(); ASSERT(succFreq >= removedFreq, "sanity check"); - succ->SetFrequency(succFreq - removedFreq); + succ->SetFrequency(static_cast(succFreq - removedFreq)); succ->SetSuccFreq(0, succ->GetFrequency()); } DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index c3333b16cf..fdc0f96022 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -213,7 +213,7 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out); uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp index 849b262239..4c65c5496e 100644 --- a/src/mapleall/maple_util/src/mpl_profdata.cpp +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -13,7 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "mpl_profdata.h" - +#include #include "mpl_logging.h" #include "option.h" @@ -55,16 +55,18 @@ void MplProfileData::DumpProfileData() { } void ProfileSummary::ProcessHistogram() { - int countsum = 0; - int n = histogram.size(); - for (int i = n - 1; i >= 0; i--) { - countsum += histogram[i].countNums; - histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + size_t countsum = 0; + size_t n = static_cast(histogram.size()); + enum PERCENTAGE {percent = 100}; + for (int32 i = n - 1; i >= 0; i--) { + countsum += histogram[static_cast(i)].countNums; + histogram[static_cast(i)].countRatio = std::round( + (static_cast(countsum) / static_cast(totalCount)) * percent); } } -#define HOTRATIO 90 uint64_t MplProfileData::GetHotThreshold() { + enum HOTNESS {HOTRATIO = 90}; for (auto &it : summary.GetHistogram()) { if (it.countRatio >= HOTRATIO) { hotCountThreshold = it.startValue; @@ -76,7 +78,8 @@ uint64_t MplProfileData::GetHotThreshold() { } } // should not be here - return 100; + const int unlikelyHot = 100; + return unlikelyHot; } bool MplProfileData::IsHotCallSite(uint64_t freq) { diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index c333420826..150b8c942d 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -597,7 +597,7 @@ size_t GetSleb128Size(int32_t v) { } // encode signed to output stream -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out) { bool more; uint32_t count = 0; do { @@ -631,64 +631,66 @@ uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { // decode a ULEB128 value. uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; uint64_t value = 0; unsigned shift = 0; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } uint64_t slice = *p & 0x7f; - if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if ((shift >= SIXTYFOUR && slice != ZERO) || ((slice << shift) >> shift) != slice) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } value += slice << shift; shift += kGreybackOffset; - } while (*p++ >= 128); + } while (*p++ >= ONEHUNDREDTWENTYEIGHT); if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } // decode a SLEB128 value. int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; int64_t value = 0; unsigned shift = 0; uint8_t byte; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, SIXTYTHREE = 63, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } byte = *p; uint64_t slice = byte & 0x7f; - if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || - (shift == 63 && slice != 0 && slice != 0x7f)) { + if ((shift >= SIXTYFOUR && slice != (value < static_cast(ZERO) ? 0x7f : 0x00)) || + (shift == SIXTYTHREE && slice != ZERO && slice != 0x7f)) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } - value |= slice << shift; + value |= static_cast(slice << shift); shift += kGreybackOffset; ++p; - } while (byte >= 128); + } while (byte >= ONEHUNDREDTWENTYEIGHT); // Sign extend negative numbers if needed. - if (shift < 64 && (byte & 0x40)) { - value |= (-1LL) << shift; + if (shift < SIXTYFOUR && (byte & 0x40)) { + value |= static_cast(0xffffffffffffffff) << shift; } if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index e0d6984461..f3850e2788 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -436,10 +436,10 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee } // use maple instrument profile if (Options::profileUse) { - if (!caller.GetFuncProfData()) return false; - int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) {return false;} + int64_t freq = static_cast(caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID())); ASSERT(freq > 0, "sanity check"); - return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); + return module.GetMapleProfile()->IsHotCallSite(static_cast(freq)); } return module.GetProfile().CheckFuncHot(caller.GetName()); } diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp index 95bd0febdd..b8c73fa36d 100644 --- a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -91,18 +91,18 @@ int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { int MplProfDataParser::ReadMapleProfileData() { std::string mprofDataFile = Options::profile; if (mprofDataFile.empty()) { - if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { - mprofDataFile.append(env_gcovprefix); + if (const char *envGcovprefix = std::getenv("GCOV_PREFIX")) { + static_cast(mprofDataFile.append(envGcovprefix)); if (mprofDataFile.back() != '/') { - mprofDataFile.append("/"); + static_cast(mprofDataFile.append("/")); } if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; } uint32_t stripnum = 0; - if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { - std::string strip(env_gcovprefixstrip); - stripnum = std::stoi(strip); + if (const char *envGcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(envGcovprefixstrip); + stripnum = static_cast(std::stoi(strip)); if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; } @@ -124,7 +124,7 @@ int MplProfDataParser::ReadMapleProfileData() { LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; } CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); - mprofDataFile.append(profDataFileName); + static_cast(mprofDataFile.append(profDataFileName)); } else { // if gcov_prefix is not set, find .mprofdata according to m.profiledata mprofDataFile = m.GetProfileDataFileName(); @@ -133,7 +133,7 @@ int MplProfDataParser::ReadMapleProfileData() { } } // add .mprofdata - mprofDataFile.append(namemangler::kMplProfFileNameExt); + static_cast(mprofDataFile.append(namemangler::kMplProfFileNameExt)); } ASSERT(!mprofDataFile.empty(), "null check"); if (dumpDetail) { @@ -148,18 +148,18 @@ int MplProfDataParser::ReadMapleProfileData() { return 1; } // get length of file - inputStream.seekg(0, std::ios::end); - uint32_t length = inputStream.tellg(); - inputStream.seekg(0, std::ios::beg); + static_cast(inputStream.seekg(0, std::ios::end)); + uint32_t length = static_cast(inputStream.tellg()); + static_cast(inputStream.seekg(0, std::ios::beg)); const uint32_t sizeThreshold = 1024 * 10; CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); std::unique_ptr buffer = std::make_unique(length); - inputStream.read(buffer.get(), length); + static_cast(inputStream.read(buffer.get(), length)); inputStream.close(); // read 1st part summary ProfileSummaryImport summaryImport(mprofDataFile, inputStream); - summaryImport.SetPosition((uint8_t*)(buffer.get())); + summaryImport.SetPosition(reinterpret_cast(buffer.get())); int res = summaryImport.ReadSummary(profData); if (res) { LogInfo::MapleLogger() << "no summary part\n"; -- Gitee From e3ed596b63c96dc457dcb989a4dc69abbdefdad7 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Wed, 3 Aug 2022 14:45:17 -0700 Subject: [PATCH 5/7] Switch to using maple profile data file format; update frequences in various maple_me phases --- src/mapleall/maple_ipa/src/ipa_clone.cpp | 4 +- .../maple_ipa/src/ipa_phase_manager.cpp | 6 +- src/mapleall/maple_ir/include/mir_function.h | 8 +- src/mapleall/maple_ir/include/mir_lower.h | 2 +- src/mapleall/maple_ir/include/mir_module.h | 24 +- src/mapleall/maple_ir/src/mir_nodes.cpp | 21 +- src/mapleall/maple_me/include/bb.h | 33 +- src/mapleall/maple_me/include/hdse.h | 21 +- src/mapleall/maple_me/include/me_cfg.h | 39 +- src/mapleall/maple_me/include/me_loop_canon.h | 5 +- .../maple_me/include/me_loop_unrolling.h | 52 ++- .../maple_me/include/me_profile_use.h | 5 +- src/mapleall/maple_me/include/pme_emit.h | 2 +- src/mapleall/maple_me/src/bb.cpp | 43 ++- src/mapleall/maple_me/src/hdse.cpp | 59 ++- src/mapleall/maple_me/src/me_bb_layout.cpp | 84 ++-- src/mapleall/maple_me/src/me_cfg.cpp | 251 +++++++----- .../maple_me/src/me_critical_edge.cpp | 22 +- src/mapleall/maple_me/src/me_dse.cpp | 10 +- src/mapleall/maple_me/src/me_hdse.cpp | 23 +- src/mapleall/maple_me/src/me_loop_canon.cpp | 60 ++- .../maple_me/src/me_loop_inversion.cpp | 112 +++--- .../maple_me/src/me_loop_unrolling.cpp | 165 ++++---- src/mapleall/maple_me/src/me_profile_use.cpp | 49 ++- .../maple_me/src/me_value_range_prop.cpp | 103 +++++ src/mapleall/maple_me/src/optimizeCFG.cpp | 364 ++++++++++-------- src/mapleall/maple_util/BUILD.gn | 1 + .../maple_util/include/mpl_profdata.h | 203 ++++++++++ src/mapleall/maple_util/include/namemangler.h | 5 + src/mapleall/maple_util/src/mpl_profdata.cpp | 100 +++++ src/mapleall/maple_util/src/namemangler.cpp | 105 ++++- src/mapleall/mpl2mpl/BUILD.gn | 2 +- src/mapleall/mpl2mpl/include/gcov_parser.h | 117 ------ .../mpl2mpl/include/inline_transformer.h | 5 +- .../mpl2mpl/include/mpl_profdata_parser.h | 118 ++++++ src/mapleall/mpl2mpl/src/call_graph.cpp | 40 +- src/mapleall/mpl2mpl/src/gen_profile.cpp | 4 +- src/mapleall/mpl2mpl/src/inline.cpp | 61 +-- .../mpl2mpl/src/inline_transformer.cpp | 17 +- .../mpl2mpl/src/module_phase_manager.cpp | 4 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 204 ++++++++++ 41 files changed, 1803 insertions(+), 750 deletions(-) create mode 100644 src/mapleall/maple_util/include/mpl_profdata.h create mode 100644 src/mapleall/maple_util/src/mpl_profdata.cpp delete mode 100644 src/mapleall/mpl2mpl/include/gcov_parser.h create mode 100644 src/mapleall/mpl2mpl/include/mpl_profdata_parser.h create mode 100644 src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp diff --git a/src/mapleall/maple_ipa/src/ipa_clone.cpp b/src/mapleall/maple_ipa/src/ipa_clone.cpp index ff25da0c85..9b32d5cc3a 100644 --- a/src/mapleall/maple_ipa/src/ipa_clone.cpp +++ b/src/mapleall/maple_ipa/src/ipa_clone.cpp @@ -140,9 +140,9 @@ MIRFunction *IpaClone::IpaCloneFunctionWithFreq(MIRFunction &originalFunction, newFunc->SetBaseClassFuncNames(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(fullName)); newFunc->GetFuncSymbol()->SetAppearsInCode(true); newFunc->SetPuidxOrigin(newFunc->GetPuidx()); - GcovFuncInfo *origProfData = originalFunction.GetFuncProfData(); + FuncProfInfo *origProfData = originalFunction.GetFuncProfData(); auto *moduleMp = mirBuilder.GetMirModule().GetMemPool(); - GcovFuncInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), + FuncProfInfo *newProfData = moduleMp->New(&mirBuilder.GetMirModule().GetMPAllocator(), newFunc->GetPuidx(), 0, 0); // skip checksum information newFunc->SetFuncProfData(newProfData); newProfData->SetFuncFrequency(callSiteFreq); diff --git a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp index b3fc2d7ba2..f477c8fa90 100644 --- a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp +++ b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp @@ -14,7 +14,7 @@ */ #include "ipa_phase_manager.h" #include "pme_emit.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -102,8 +102,8 @@ void IpaSccPM::GetAnalysisDependence(maple::AnalysisDep &aDep) const { aDep.AddPreserved(); aDep.AddPreserved(); if (Options::profileUse) { - aDep.AddRequired(); - aDep.AddPreserved(); + aDep.AddRequired(); + aDep.AddPreserved(); } } diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 161611f558..4b1a08acfb 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1271,13 +1271,13 @@ class MIRFunction { InlineSummary *GetOrCreateInlineSummary(); - void SetFuncProfData(GcovFuncInfo *data) { + void SetFuncProfData(FuncProfInfo *data) { funcProfData = data; } - GcovFuncInfo* GetFuncProfData() { + FuncProfInfo* GetFuncProfData() { return funcProfData; } - GcovFuncInfo* GetFuncProfData() const { + FuncProfInfo* GetFuncProfData() const { return funcProfData; } void SetStmtFreq(uint32_t stmtID, uint64_t freq) { @@ -1402,7 +1402,7 @@ class MIRFunction { uint32 nCtrs = 0; // number of counters uint64 fileLinenoChksum = 0; uint64 cfgChksum = 0; - GcovFuncInfo *funcProfData = nullptr; + FuncProfInfo *funcProfData = nullptr; InlineSummary *inlineSummary = nullptr; void DumpFlavorLoweredThanMmpl() const; MIRFuncType *ReconstructFormals(const std::vector &symbols, bool clearOldArgs); diff --git a/src/mapleall/maple_ir/include/mir_lower.h b/src/mapleall/maple_ir/include/mir_lower.h index c2261326d1..e4229aa853 100644 --- a/src/mapleall/maple_ir/include/mir_lower.h +++ b/src/mapleall/maple_ir/include/mir_lower.h @@ -142,7 +142,7 @@ class MIRLower { virtual bool InLFO() const { return false; } - GcovFuncInfo *GetFuncProfData() const { + FuncProfInfo *GetFuncProfData() const { return mirFunc->GetFuncProfData(); } void CopyStmtFrequency(StmtNode *newStmt, StmtNode *oldStmt) { diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index 37c54a99b3..f5965f008d 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -22,7 +22,7 @@ #include "muid.h" #include "profile.h" #include "namemangler.h" -#include "gcov_profile.h" +#include "mpl_profdata.h" #if MIR_FEATURE_FULL #include #include @@ -268,11 +268,11 @@ class MIRModule { return profile; } - GcovProfileData* GetGcovProfile() { - return gcovProfile; + MplProfileData* GetMapleProfile() { + return mplProfile; } - void SetGcovProfile(GcovProfileData* info) { - gcovProfile = info; + void SetMapleProfile(MplProfileData* info) { + mplProfile = info; } void SetSomeSymbolNeedForDecl(bool s) { @@ -341,11 +341,13 @@ class MIRModule { } std::string GetProfileDataFileName() const { - std::string profileDataFileName = fileName.substr(0, fileName.find_last_of(".")); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '.', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '-', '_'); - std::replace(profileDataFileName.begin(), profileDataFileName.end(), '/', '_'); - profileDataFileName = profileDataFileName + namemangler::kProfFileNameExt; + std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); + char *gcov_path = std::getenv("GCOV_PREFIX"); + std::string gcov_prefix = gcov_path ? gcov_path : ""; + if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { + gcov_prefix.append("/"); + } + profileDataFileName = gcov_prefix + profileDataFileName; return profileDataFileName; } @@ -710,7 +712,7 @@ class MIRModule { MapleSet symbolSet; MapleVector symbolDefOrder; Profile profile; - GcovProfileData* gcovProfile; + MplProfileData* mplProfile; bool someSymbolNeedForwDecl = false; // some symbols' addressses used in initialization std::ostream &out; diff --git a/src/mapleall/maple_ir/src/mir_nodes.cpp b/src/mapleall/maple_ir/src/mir_nodes.cpp index e8113fb657..fbdd3bae68 100644 --- a/src/mapleall/maple_ir/src/mir_nodes.cpp +++ b/src/mapleall/maple_ir/src/mir_nodes.cpp @@ -686,10 +686,11 @@ void AddroflabelNode::Dump(int32 indent [[maybe_unused]]) const { void StmtNode::DumpBase(int32 indent) const { srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs - if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData() && - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) >= 0) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } PrintIndentation(indent); LogInfo::MapleLogger() << kOpcodeInfo.GetTableItemAt(GetOpCode()).name; @@ -1329,8 +1330,10 @@ void BlockNode::Dump(int32 indent, const MIRSymbolTable *theSymTab, MIRPregTable srcPosition.DumpLoc(lastPrintedLineNum, lastPrintedColumnNum); // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } for (auto &stmt : GetStmtNodes()) { stmt.Dump(indent + 1); @@ -1345,8 +1348,10 @@ void LabelNode::Dump(int32 indent [[maybe_unused]]) const { } // dump stmtFreqs if (Options::profileUse && theMIRModule->CurFunction()->GetFuncProfData()) { - LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << - theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID()) << "\n"; + int64_t freq = static_cast(theMIRModule->CurFunction()->GetFuncProfData()->GetStmtFreq(GetStmtID())); + if (freq >= 0) { + LogInfo::MapleLogger() << "stmtID " << GetStmtID() << " freq " << freq << "\n"; + } } LogInfo::MapleLogger() << "@" << theMIRModule->CurFunction()->GetLabelName(labelIdx) << " "; } diff --git a/src/mapleall/maple_me/include/bb.h b/src/mapleall/maple_me/include/bb.h index 24d5327261..e0c01e71e8 100644 --- a/src/mapleall/maple_me/include/bb.h +++ b/src/mapleall/maple_me/include/bb.h @@ -14,18 +14,18 @@ */ #ifndef MAPLE_ME_INCLUDE_BB_H #define MAPLE_ME_INCLUDE_BB_H -#include "utils.h" #include "mpl_number.h" -#include "ptr_list_ref.h" #include "orig_symbol.h" -#include "ver_symbol.h" +#include "ptr_list_ref.h" #include "ssa.h" +#include "utils.h" +#include "ver_symbol.h" namespace maple { -class MeStmt; // circular dependency exists, no other choice -class MePhiNode; // circular dependency exists, no other choice +class MeStmt; // circular dependency exists, no other choice +class MePhiNode; // circular dependency exists, no other choice class PiassignMeStmt; // circular dependency exists, no other choice -class IRMap; // circular dependency exists, no other choice +class IRMap; // circular dependency exists, no other choice enum BBKind { kBBUnknown, // uninitialized kBBCondGoto, @@ -406,8 +406,17 @@ class BB { ASSERT(idx >= 0 && idx <= succFreq.size(), "sanity check"); succFreq[static_cast(idx)] = freq; } + void AddSuccFreq(uint64 freq, size_t pos = UINT32_MAX) { + ASSERT((pos <= succFreq.size() || pos == UINT32_MAX), "Invalid position."); + if (pos == UINT32_MAX) { + succFreq.push_back(freq); + } else { + succFreq.insert(succFreq.begin() + pos, freq); + } + } + // update edge frequency - void UpdateEdgeFreqs(); + void UpdateEdgeFreqs(bool updateSuccFreq = true); const MapleVector &GetSucc() const { return succ; @@ -487,7 +496,7 @@ class BB { auto iter = std::find(succ.begin(), succ.end(), bb); CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d", succFreq.size(), - succ.size()); + succ.size()); const size_t idx = static_cast(std::distance(succ.begin(), iter)); succFreq[idx] = freq; } @@ -496,7 +505,7 @@ class BB { succFreq.resize(succ.size()); } - BB* GetGroup() const { + BB *GetGroup() const { return group; } @@ -524,12 +533,13 @@ class BB { int GetPredIndex(const BB &predBB) const; int GetSuccIndex(const BB &succBB) const; void RemovePhiOpnd(int index); + private: bool IsInList(const MapleVector &bbList) const; int RemoveBBFromVector(MapleVector &bbVec) const; BBId id; - LabelIdx bbLabel = 0; // the BB's label + LabelIdx bbLabel = 0; // the BB's label MapleVector pred; // predecessor list MapleVector succ; // successor list // record the edge freq from curBB to succ BB @@ -540,8 +550,10 @@ class BB { uint32 frequency = 0; BBKind kind = kBBUnknown; uint32 attributes = 0; + public: StmtNodes stmtNodeList; + private: MeStmts meStmtList; BB *group; @@ -586,6 +598,7 @@ class SCCOfBBs { BB *GetEntry() { return entry; } + private: uint32 id; BB *entry; diff --git a/src/mapleall/maple_me/include/hdse.h b/src/mapleall/maple_me/include/hdse.h index c5a637c314..a00188d9c5 100644 --- a/src/mapleall/maple_me/include/hdse.h +++ b/src/mapleall/maple_me/include/hdse.h @@ -14,17 +14,17 @@ */ #ifndef MAPLE_ME_INCLUDE_HDSE_H #define MAPLE_ME_INCLUDE_HDSE_H +#include "alias_class.h" #include "bb.h" -#include "irmap.h" #include "dominance.h" -#include "alias_class.h" +#include "irmap.h" namespace maple { class MeIRMap; class HDSE { public: - HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, - Dominance &pDom, IRMap &map, const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) + HDSE(MIRModule &mod, const MapleVector &bbVec, BB &commonEntryBB, BB &commonExitBB, Dominance &pDom, IRMap &map, + const AliasClass *aliasClass, bool enabledDebug = false, bool decouple = false) : hdseDebug(enabledDebug), mirModule(mod), bbVec(bbVec), @@ -48,6 +48,12 @@ class HDSE { void SetRemoveRedefine(bool val) { removeRedefine = val; } + void SetUpdateFreq(bool update) { + updateFreq = update; + } + bool UpdateFreq() { + return updateFreq; + } bool hdseDebug; bool hdseKeepRef = false; @@ -73,10 +79,11 @@ class HDSE { // Or the meExpr is opnd of a same type meExpr static const uint8 kExprTypeNotNull = 2; bool decoupleStatic = false; - bool needUNClean = false; // used to record if there's unreachable BB + bool needUNClean = false; // used to record if there's unreachable BB bool removeRedefine = false; // used to control if run ResolveContinuousRedefine() - MapleVector verstUseCounts; // index is vstIdx - std::forward_list backSubsCands; // backward substitution candidates + bool updateFreq = false; + MapleVector verstUseCounts; // index is vstIdx + std::forward_list backSubsCands; // backward substitution candidates private: void DseInit(); diff --git a/src/mapleall/maple_me/include/me_cfg.h b/src/mapleall/maple_me/include/me_cfg.h index d04e9addb1..8465e37e75 100644 --- a/src/mapleall/maple_me/include/me_cfg.h +++ b/src/mapleall/maple_me/include/me_cfg.h @@ -14,12 +14,13 @@ */ #ifndef MAPLE_ME_INCLUDE_ME_CFG_H #define MAPLE_ME_INCLUDE_ME_CFG_H -#include "me_function.h" #include "maple_phase.h" +#include "me_function.h" namespace maple { class MeCFG : public AnalysisResult { using BBPtrHolder = MapleVector; + public: using value_type = BBPtrHolder::value_type; using size_type = BBPtrHolder::size_type; @@ -86,7 +87,9 @@ class MeCFG : public AnalysisResult { hasDoWhile = hdw; } - MapleAllocator &GetAlloc() { return mecfgAlloc; } + MapleAllocator &GetAlloc() { + return mecfgAlloc; + } void SetNextBBId(uint32 currNextBBId) { nextBBId = currNextBBId; @@ -98,7 +101,9 @@ class MeCFG : public AnalysisResult { --nextBBId; } - MapleVector &GetAllBBs() { return bbVec; } + MapleVector &GetAllBBs() { + return bbVec; + } iterator begin() { return bbVec.begin(); @@ -296,8 +301,19 @@ class MeCFG : public AnalysisResult { void ConstructBBFreqFromStmtFreq(); void ConstructStmtFreq(); void ConstructEdgeFreqFromBBFreq(); - void UpdateEdgeFreqWithNewBBFreq(); - void VerifyBBFreq(); + void UpdateEdgeFreqWithBBFreq(); + int VerifyBBFreq(bool checkFatal = false); + void SetUpdateCFGFreq(bool b) { + updateFreq = b; + } + bool UpdateCFGFreq() const { + return updateFreq; + } + bool DumpIRProfileFile() const { + return dumpIRProfileFile; + } + void ClearFuncFreqInfo(); + private: void AddCatchHandlerForTryBB(BB &bb, MapleVector &exitBlocks); std::string ConstructFileNameToDump(const std::string &prefix) const; @@ -316,11 +332,14 @@ class MeCFG : public AnalysisResult { MapleAllocator mecfgAlloc; MeFunction &func; MapleSet patternSet; - BBPtrHolder bbVec; + BBPtrHolder bbVec; MapleUnorderedMap labelBBIdMap; MapleUnorderedMap bbTryNodeMap; // maps isTry bb to its try stmt MapleUnorderedMap endTryBB2TryBB; // maps endtry bb to its try bb bool hasDoWhile = false; + // following 2 variable are used in profileUse + bool updateFreq = false; // true to maintain cfg frequency in transform phase + bool dumpIRProfileFile = false; // true to dump cfg to files uint32 nextBBId = 0; // BB SCC @@ -331,10 +350,10 @@ class MeCFG : public AnalysisResult { }; MAPLE_FUNC_PHASE_DECLARE_BEGIN(MEMeCfg, MeFunction) - MeCFG *GetResult() { - return theCFG; - } - MeCFG *theCFG = nullptr; +MeCFG *GetResult() { + return theCFG; +} +MeCFG *theCFG = nullptr; MAPLE_MODULE_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(MECfgVerifyFrequency, MeFunction) MAPLE_FUNC_PHASE_DECLARE_END diff --git a/src/mapleall/maple_me/include/me_loop_canon.h b/src/mapleall/maple_me/include/me_loop_canon.h index 248a185127..cd76626574 100644 --- a/src/mapleall/maple_me/include/me_loop_canon.h +++ b/src/mapleall/maple_me/include/me_loop_canon.h @@ -21,7 +21,8 @@ namespace maple { // convert loop to do-while format class MeLoopCanon { public: - MeLoopCanon(MeFunction &f, bool enableDebugFunc) : func(f), isDebugFunc(enableDebugFunc) {} + MeLoopCanon(MeFunction &f, bool enableDebugFunc, bool updateFreq) + : func(f), isDebugFunc(enableDebugFunc), updateFreqs(updateFreq) {} virtual ~MeLoopCanon() = default; void NormalizationExitOfLoop(IdentifyLoops &meLoop); void NormalizationHeadAndPreHeaderOfLoop(Dominance &dom); @@ -33,6 +34,7 @@ class MeLoopCanon { void ResetIsCFGChange() { isCFGChange = false; } + private: void FindHeadBBs(Dominance &dom, const BB *bb, std::map> &heads) const; void SplitPreds(const std::vector &splitList, BB *splittedBB, BB *mergedBB); @@ -44,6 +46,7 @@ class MeLoopCanon { MeFunction &func; bool isDebugFunc; bool isCFGChange = false; + bool updateFreqs = false; }; MAPLE_FUNC_PHASE_DECLARE(MELoopCanon, MeFunction) diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 4b0c81c075..1e5f57be8f 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -14,22 +14,23 @@ */ #ifndef MAPLE_ME_INCLUDE_LOOP_UNROLLING_H #define MAPLE_ME_INCLUDE_LOOP_UNROLLING_H -#include "me_scalar_analysis.h" +#include "me_cfg.h" +#include "me_dominance.h" #include "me_function.h" -#include "me_irmap_build.h" #include "me_ir.h" -#include "me_ssa_update.h" -#include "me_dominance.h" +#include "me_irmap_build.h" #include "me_loop_analysis.h" +#include "me_scalar_analysis.h" +#include "me_ssa_update.h" #include "profile.h" -#include "me_cfg.h" namespace maple { constexpr uint32 kMaxCost = 100; -constexpr uint8 unrollTimes[3] = { 8, 4, 2 }; // unrollTimes +constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll { + enum ReturnKindOfFullyUnroll + { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, @@ -37,14 +38,26 @@ class LoopUnrolling { LoopUnrolling(MeFunction &f, LoopDesc &l, MeIRMap &map, const MapleAllocator &alloc, std::map>> &candsTemp) - : func(&f), cfg(f.GetCfg()), loop(&l), irMap(&map), mpAllocator(alloc), - cands(candsTemp), lastNew2OldBB(mpAllocator.Adapter()), + : func(&f), + cfg(f.GetCfg()), + loop(&l), + irMap(&map), + mpAllocator(alloc), + cands(candsTemp), + lastNew2OldBB(mpAllocator.Adapter()), profValid(func->IsIRProfValid()) {} ~LoopUnrolling() = default; ReturnKindOfFullyUnroll LoopFullyUnroll(int64 tripCount); bool LoopPartialUnrollWithConst(uint64 tripCount); bool LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j); bool LoopUnrollingWithConst(uint64 tripCount, bool onlyFully = false); + void SetInstrumentProf(bool useInstrument) { + instrumentProf = useInstrument; + profValid = useInstrument; + } + bool GetInstrumentProf() const { + return instrumentProf; + } private: bool SplitCondGotoBB(); @@ -53,14 +66,12 @@ class LoopUnrolling { void SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, const BB &exitBB, LabelIdx oldlabIdx); - void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB); - void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); - void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop); + void ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, BB &newHeadBB); + void CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); + void CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop); void UpdateCondGotoBB(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr); void UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, uint32 offset); void CreateIndVarAndCondGotoStmt(CR &cr, CRNode &varNode, BB &preCondGoto, uint32 unrollTime, uint32 i); @@ -85,7 +96,7 @@ class LoopUnrolling { bool canUnroll = true; MeFunction *func; - MeCFG *cfg; + MeCFG *cfg; LoopDesc *loop; MeIRMap *irMap; MapleAllocator mpAllocator; @@ -100,6 +111,7 @@ class LoopUnrolling { bool firstResetForAfterInsertGoto = true; bool resetFreqForUnrollWithVar = false; bool isUnrollWithVar = false; + bool instrumentProf = false; // use instrumented profiling }; class LoopUnrollingExecutor { @@ -109,8 +121,8 @@ class LoopUnrollingExecutor { static bool enableDebug; static bool enableDump; - void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc); + void ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc); bool IsCFGChange() const { return isCFGChange; } diff --git a/src/mapleall/maple_me/include/me_profile_use.h b/src/mapleall/maple_me/include/me_profile_use.h index a6a0be8df7..2014e80026 100644 --- a/src/mapleall/maple_me/include/me_profile_use.h +++ b/src/mapleall/maple_me/include/me_profile_use.h @@ -137,8 +137,7 @@ class MeProfUse : public PGOInstrument { bool IsSuccUseProf() const { return succCalcuAllEdgeFreq; } - bool GcovRun(); - GcovFuncInfo *GetFuncData(); + bool MapleProfRun(); bool CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, const std::string &tag); private: bool IsAllZero(Profile::BBInfo &result) const; @@ -147,6 +146,8 @@ class MeProfUse : public PGOInstrument { void ComputeEdgeFreq(); void InitBBEdgeInfo(); void ComputeBBFreq(BBUseInfo &bbInfo, bool &changed); + FuncProfInfo *GetFuncData(); + uint64 SumEdgesCount(const MapleVector &edges) const; BBUseInfo *GetBBUseInfo(const BB &bb) const; BBUseInfo *GetOrCreateBBUseInfo(const BB &bb) ; diff --git a/src/mapleall/maple_me/include/pme_emit.h b/src/mapleall/maple_me/include/pme_emit.h index 85cb7996ec..e9a4628409 100644 --- a/src/mapleall/maple_me/include/pme_emit.h +++ b/src/mapleall/maple_me/include/pme_emit.h @@ -79,7 +79,7 @@ class PreMeEmitter : public AnalysisResult { MapleAllocator* GetCodeMPAlloc() { return codeMPAlloc; } MapleMap *GetPreMeStmtExtensionMap() { return &preMeStmtExtensionMap; } MapleMap *GetPreMeExprExtensionMap() { return &preMeExprExtensionMap; } - GcovFuncInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } + FuncProfInfo *GetFuncProfData() { return mirFunc->GetFuncProfData(); } private: ArrayNode *ConvertToArray(BaseNode *x, TyIdx ptrTyIdx); diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 7e7e7e5490..290a3c6caa 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,10 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" + +#include + +#include "me_ir.h" +#include "me_ssa.h" #include "mempool_allocator.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "me_ir.h" namespace maple { std::string BB::StrAttribute() const { @@ -80,8 +83,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse) { - mod->GetOut() << " freq: " << frequency << " "; + if (Options::profileUse && frequency >= 0) { + mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; mod->GetOut() << "preds: "; @@ -299,8 +302,8 @@ void BB::MoveAllPredToSucc(BB *newSucc, BB *commonEntry) { } 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 + if (IsSuccBB(*firstPred)) { // avoid replacing twice + firstPred->ReplaceSucc(this, newSucc, true); // firstPred will be removed from this->pred } } } @@ -336,8 +339,8 @@ void BB::MoveAllSuccToPred(BB *newPred, BB *commonExit) { } else { while (!GetSucc().empty()) { BB *firstSucc = GetSucc(0); - if (IsPredBB(*firstSucc)) { // avoid replacing twice - firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ + if (IsPredBB(*firstSucc)) { // avoid replacing twice + firstSucc->ReplacePred(this, newPred); // firstSucc will be removed from this->succ } } } @@ -476,23 +479,31 @@ void BB::DumpMePhiList(const IRMap *irMap) { } } -// bb frequency is changed in tranform phase -// update its succ frequency by scaled value -void BB::UpdateEdgeFreqs() { +// update edge frequency by scaled value when bb frequency is changed +void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { int len = GetSucc().size(); ASSERT(len == GetSuccFreq().size(), "sanity check"); int64_t succFreqs = 0; for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - // early return if frequency is consistent - if (len == 0 || succFreqs == GetFrequency()) { - return; - } - for (size_t i = 0; i < len; ++i) { + int diff = abs(succFreqs - GetFrequency()); + if (len == 0 || diff <= 1) return; + int64_t scaledSum = 0; + for (int i = 0; i < len; i++) { int64_t sfreq = GetSuccFreq()[i]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); + scaledSum += scalefreq; SetSuccFreq(i, scalefreq); + // update succ frequency with new difference if needed + if (updateBBFreqOfSucc) { + auto *succ = GetSucc(i); + int64_t diff = scalefreq - sfreq; + int64_t succBBnewFreq = succ->GetFrequency() + diff; + if (succBBnewFreq >= 0) { + succ->SetFrequency(succBBnewFreq); + } + } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 4badba2ad5..99748916e6 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -13,20 +13,22 @@ * See the Mulan PSL v2 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 "opcode_info.h" +#include "ssa_mir_nodes.h" #include "utils.h" +#include "ver_symbol.h" namespace maple { using namespace utils; void HDSE::DetermineUseCounts(MeExpr *x) { if (x->GetMeOp() == kMeOpVar) { - VarMeExpr *varmeexpr = static_cast(x); + VarMeExpr *varmeexpr = static_cast(x); verstUseCounts[varmeexpr->GetVstIdx()]++; return; } @@ -42,7 +44,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (dass->GetRHS()->GetMeOp() != kMeOpVar && dass->GetRHS()->GetMeOp() != kMeOpReg) { return; } - ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); + ScalarMeExpr *lhsscalar = static_cast(dass->GetLHS()); OriginalSt *ost = lhsscalar->GetOst(); if (!ost->IsLocal()) { return; @@ -51,7 +53,7 @@ void HDSE::CheckBackSubsCandidacy(DassignMeStmt *dass) { if (ty->GetPrimType() == PTY_agg && ty->GetSize() <= 16) { return; } - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (rhsscalar->GetDefBy() != kDefByMustDef) { return; } @@ -247,6 +249,13 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } } bb.SetKind(kBBFallthru); + if (UpdateFreq()) { + int64_t succ0Freq = bb.GetSuccFreq()[0]; + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + } } // A ivar contained in stmt if (stmt2NotNullExpr.find(mestmt) != stmt2NotNullExpr.end()) { @@ -269,8 +278,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // skip fold conditional branch because it may break recorded IfInfo. bool isPme = mirModule.CurFunction()->GetMeFunc()->GetPreMeFunc() != nullptr; - if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch - CondGotoMeStmt *condbr = static_cast(mestmt); + if (mestmt->IsCondBr() && !isPme) { // see if foldable to unconditional branch + CondGotoMeStmt *condbr = static_cast(mestmt); + int64_t removedFreq = 0; if (!mirModule.IsJavaModule() && condbr->GetOpnd()->GetMeOp() == kMeOpConst) { CHECK_FATAL(IsPrimitiveInteger(condbr->GetOpnd()->GetPrimType()), "MeHDSE::DseProcess: branch condition must be integer type"); @@ -278,6 +288,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { (condbr->GetOp() == OP_brfalse && !condbr->GetOpnd()->IsZero())) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().back(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -288,6 +301,9 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } else { // change to unconditional branch BB *succbb = bb.GetSucc().front(); + if (UpdateFreq()) { + removedFreq = bb.GetSuccFreq().front(); + } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { needUNClean = true; @@ -297,6 +313,11 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { GotoMeStmt *gotomestmt = irMap.New(condbr->GetOffset()); bb.ReplaceMeStmt(condbr, gotomestmt); } + if (UpdateFreq()) { + bb.GetSuccFreq().resize(1); + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + } } else { DetermineUseCounts(condbr->GetOpnd()); } @@ -305,17 +326,17 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { DetermineUseCounts(mestmt->GetOpnd(i)); } if (mestmt->GetOp() == OP_dassign) { - CheckBackSubsCandidacy(static_cast(mestmt)); + CheckBackSubsCandidacy(static_cast(mestmt)); } } } mestmt = nextstmt; } // update verstUseCOunts for uses in phi operands - for (std::pair phipair : bb.GetMePhiList()) { + for (std::pair phipair : bb.GetMePhiList()) { if (phipair.second->GetIsLive()) { for (ScalarMeExpr *phiOpnd : phipair.second->GetOpnds()) { - VarMeExpr *varx = dynamic_cast(phiOpnd); + VarMeExpr *varx = dynamic_cast(phiOpnd); if (varx) { verstUseCounts[varx->GetVstIdx()]++; } @@ -334,7 +355,7 @@ bool HDSE::NeedNotNullCheck(MeExpr &meExpr, const BB &bb) { if (meExpr.GetOp() == OP_addrof) { return false; } - if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { + if (meExpr.GetOp() == OP_iaddrof && static_cast(meExpr).GetFieldID() > 0) { return false; } @@ -446,8 +467,7 @@ void HDSE::MarkRegDefByStmt(RegMeExpr ®MeExpr) { MarkPhiRequired(regMeExpr.GetDefPhi()); break; case kDefByChi: { - ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, - "MarkRegDefByStmt: preg cannot be defined by chi"); + ASSERT(regMeExpr.GetOst()->GetIndirectLev() > 0, "MarkRegDefByStmt: preg cannot be defined by chi"); auto &defChi = regMeExpr.GetDefChi(); MarkChiNodeRequired(defChi); break; @@ -587,8 +607,7 @@ bool HDSE::ExprNonDeletable(const MeExpr &meExpr) const { } case kMeOpVar: { auto &varMeExpr = static_cast(meExpr); - return varMeExpr.IsVolatile() || - (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); + return varMeExpr.IsVolatile() || (decoupleStatic && varMeExpr.GetOst()->GetMIRSymbol()->IsGlobal()); } case kMeOpIvar: { auto &opIvar = static_cast(meExpr); @@ -618,7 +637,7 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { switch (op) { case OP_dassign: { auto &dasgn = static_cast(meStmt); - VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); + VarMeExpr *varMeExpr = static_cast(dasgn.GetVarLHS()); return (varMeExpr != nullptr && varMeExpr->IsVolatile()) || ExprNonDeletable(*dasgn.GetRHS()) || (hdseKeepRef && dasgn.Propagated()) || dasgn.GetWasMayDassign() || (decoupleStatic && varMeExpr != nullptr && varMeExpr->GetOst()->GetMIRSymbol()->IsGlobal()); @@ -632,8 +651,8 @@ bool HDSE::HasNonDeletableExpr(const MeStmt &meStmt) const { 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()); + return ivarMeExpr.IsVolatile() || ivarMeExpr.IsFinal() || ExprNonDeletable(*iasgn.GetLHSVal()->GetBase()) || + ExprNonDeletable(*iasgn.GetRHS()); } default: return false; @@ -862,4 +881,4 @@ void HDSE::DoHDSE() { } RemoveNotRequiredStmts(); } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_me/src/me_bb_layout.cpp b/src/mapleall/maple_me/src/me_bb_layout.cpp index 850a013b07..8c5612db86 100644 --- a/src/mapleall/maple_me/src/me_bb_layout.cpp +++ b/src/mapleall/maple_me/src/me_bb_layout.cpp @@ -13,13 +13,14 @@ * See the Mulan PSL v2 for more details. */ #include "me_bb_layout.h" -#include "me_cfg.h" + #include "bb.h" +#include "maple_phase.h" +#include "me_cfg.h" +#include "me_critical_edge.h" #include "me_irmap.h" #include "me_option.h" #include "me_predict.h" -#include "maple_phase.h" -#include "me_critical_edge.h" // This BB layout strategy strictly obeys source ordering when inside try blocks. // This Optimization will reorder the bb layout. it start from the first bb of func. @@ -114,12 +115,10 @@ void BBLayout::BuildChainForLoops() { auto &loops = meLoop->GetMeLoops(); // sort loops from inner most to outer most // need use the same sort rules as prediction? - std::stable_sort(loops.begin(), loops.end(), [](const LoopDesc *loop1, const LoopDesc *loop2) { - return loop1->nestDepth > loop2->nestDepth; - }); + std::stable_sort(loops.begin(), loops.end(), + [](const LoopDesc *loop1, const LoopDesc *loop2) { return loop1->nestDepth > loop2->nestDepth; }); // build chain for loops one by one - auto *context = - layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); + auto *context = layoutAlloc.GetMemPool()->New>(cfg->NumBBs(), false, layoutAlloc.Adapter()); for (auto *loop : loops) { BuildChainForLoop(loop, context); } @@ -188,13 +187,13 @@ void BBLayout::DoBuildChain(const BB &header, BBChain &chain, const MapleVector< } bool BBLayout::IsCandidateSucc(const BB &bb, const BB &succ, const MapleVector *context) { - if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) + if (!IsBBInCurrContext(succ, context)) { // succ must be in the current context (current loop or current func) return false; } - if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains + if (bb2chain[succ.GetBBId()] == bb2chain[bb.GetBBId()]) { // bb and succ should belong to different chains return false; } - if (succ.GetBBId() == 1) { // special case, exclude common exit BB + if (succ.GetBBId() == 1) { // special case, exclude common exit BB return false; } return true; @@ -240,7 +239,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } uint32 currEdgeFreq = static_cast(bb.GetEdgeFreq(i)); // attention: entryBB->succFreq[i] is always 0 - if (bb.GetBBId() == 0) { // special case for common entry BB + if (bb.GetBBId() == 0) { // special case for common entry BB CHECK_FATAL(bb.GetSucc().size() == 1, "common entry BB should not have more than 1 succ"); bestSucc = succ; break; @@ -253,7 +252,7 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector if (bestSucc != nullptr) { if (debugChainLayout) { LogInfo::MapleLogger() << "Select [range1 succ ]: "; - LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; + LogInfo::MapleLogger() << bb.GetBBId() << " -> " << bestSucc->GetBBId() << std::endl; } return bestSucc; } @@ -267,12 +266,12 @@ BB *BBLayout::GetBestSucc(BB &bb, const BBChain &chain, const MapleVector continue; } bool useBBFreq = false; - if (useBBFreq) { // use bb freq + if (useBBFreq) { // use bb freq if (header->GetFrequency() > bestFreq) { // find max bb freq bestFreq = header->GetFrequency(); bestSucc = header; } - } else { // use edge freq + } else { // use edge freq uint32 subBestFreq = 0; for (auto *pred : header->GetPred()) { uint32 curFreq = static_cast(pred->GetEdgeFreq(header)); @@ -595,8 +594,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { // condgoto's succ layout: [0] fallthru succ, [1] target succ, [2-...] eh succ/wontexit succ // goto's succ layout: [0] target succ, [1-...] eh succ/wontexit succ BB *brTargetBB = bb.GetKind() == kBBCondGoto ? bb.GetSucc(1) : bb.GetSucc(0); - CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), - "target is same as fallthru"); + CHECK_FATAL((bb.GetKind() != kBBCondGoto || bb.GetSucc(1) != bb.GetSucc(0)), "target is same as fallthru"); if (brTargetBB->GetAttributes(kBBAttrWontExit)) { return; } @@ -608,8 +606,7 @@ void BBLayout::OptimizeBranchTarget(BB &bb) { bbVisited[bb.GetBBId().GetIdx()] = true; OptimizeBranchTarget(*brTargetBB); // optimize stmt - BB *newTargetBB = - (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); + BB *newTargetBB = (brTargetBB->GetKind() == kBBCondGoto) ? brTargetBB->GetSucc(1) : brTargetBB->GetSucc(0); if (newTargetBB == brTargetBB) { return; } @@ -682,7 +679,7 @@ void BBLayout::AddBB(BB &bb) { // If the pred bb is goto bb and the target bb of goto bb is the current bb which is be added to layoutBBs, change the // goto bb to fallthru bb. if (layoutBBs.size() > 1) { - BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. + BB *predBB = layoutBBs.at(layoutBBs.size() - 2); // Get the pred of bb. if (predBB->GetKind() != kBBGoto) { return; } @@ -880,7 +877,6 @@ void BBLayout::RemoveUnreachable(BB &bb) { } } - void BBLayout::UpdateNewBBWithAttrTry(const BB &bb, BB &fallthru) const { auto tryBB = &bb; fallthru.SetAttributes(kBBAttrIsTry); @@ -945,6 +941,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { index--; fallthru.AddPred(*newFallthru, index); newFallthru->SetFrequency(fallthru.GetFrequency()); + if (cfg->UpdateCFGFreq()) { + newFallthru->PushBackSuccFreq(fallthru.GetFrequency()); + } if (enabledDebug) { LogInfo::MapleLogger() << "Created fallthru and goto original fallthru" << '\n'; } @@ -954,7 +953,9 @@ BB *BBLayout::CreateGotoBBAfterCondBB(BB &bb, BB &fallthru) { } void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { - if (needDealWithTryBB) { return; } + if (needDealWithTryBB) { + return; + } auto *fallthru = bb.GetSucc().front(); while (fallthru && (fallthru->GetPred().size() == 1) && (BBEmptyAndFallthru(*fallthru) || BBContainsOnlyGoto(*fallthru)) && @@ -964,7 +965,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { bb.ReplaceSucc(fallthru, newFallthru); ASSERT(fallthru->GetPred().empty(), "fallthru should not has other pred"); ChangeToFallthruFromCondGoto(bb); - bb.GetSucc().resize(1); // resize succ to 1 + bb.GetSucc().resize(1); // resize succ to 1 } else if (newFallthru->GetPred().size() == 1) { if (newFallthru->GetBBLabel() != 0) { // reset newFallthru label @@ -982,7 +983,7 @@ void BBLayout::OptimizeEmptyFallThruBB(BB &bb) { } void BBLayout::DumpBBPhyOrder() const { - LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; + LogInfo::MapleLogger() << func.GetName() << " final BB order " << '\n'; for (auto bb : layoutBBs) { LogInfo::MapleLogger() << bb->GetBBId(); if (bb != layoutBBs.back()) { @@ -1059,8 +1060,7 @@ void BBLayout::LayoutWithoutProf() { } ASSERT(!(isTry && GetTryOutstanding()), "cannot emit another try if last try has not been ended"); if (nextBB->GetAttributes(kBBAttrIsTryEnd)) { - ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || - IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), + ASSERT(cfg->GetTryBBFromEndTryBB(nextBB) == nextBB || IsBBLaidOut(cfg->GetTryBBFromEndTryBB(nextBB)->GetBBId()), "cannot emit endtry bb before its corresponding try bb"); } } @@ -1204,8 +1204,8 @@ void BBLayout::BuildEdges() { allEdges.emplace_back(layoutAlloc.GetMemPool()->New(bb, dest, w)); } } - std::stable_sort(allEdges.begin(), allEdges.end(), [](const BBEdge *edge1, const BBEdge *edge2) { - return edge1->GetWeight() > edge2->GetWeight(); }); + std::stable_sort(allEdges.begin(), allEdges.end(), + [](const BBEdge *edge1, const BBEdge *edge2) { return edge1->GetWeight() > edge2->GetWeight(); }); } BB *BBLayout::GetBBFromEdges() { @@ -1214,8 +1214,8 @@ BB *BBLayout::GetBBFromEdges() { BB *srcBB = edge->GetSrcBB(); BB *destBB = edge->GetDestBB(); if (enabledDebug) { - LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " - << srcBB->GetEdgeFreq(destBB) << '\n'; + LogInfo::MapleLogger() << srcBB->GetBBId() << "->" << destBB->GetBBId() << " freq " << srcBB->GetEdgeFreq(destBB) + << '\n'; } if (!laidOut[srcBB->GetBBId()]) { @@ -1252,7 +1252,7 @@ BB *BBLayout::NextBBProf(BB &bb) { return NextBBProf(*succBB); } // max freq intial - uint64 maxFreq = 0; + uint64 maxFreq = 0; size_t idx = 0; bool found = false; for (size_t i = 0; i < bb.GetSucc().size(); ++i) { @@ -1282,11 +1282,14 @@ void BBLayout::RebuildFreq() { auto *hook = phase->GetAnalysisInfoHook(); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MEDominance::id); hook->ForceEraseAnalysisPhase(func.GetUniqueID(), &MELoopAnalysis::id); - dom = static_cast( - hook->ForceRunAnalysisPhase>(&MEDominance::id, func))->GetResult(); + dom = static_cast(hook->ForceRunAnalysisPhase>(&MEDominance::id, func)) + ->GetResult(); meLoop = static_cast( - hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func))->GetResult(); - MePrediction::RebuildFreq(func, *dom, *meLoop); + hook->ForceRunAnalysisPhase>(&MELoopAnalysis::id, func)) + ->GetResult(); + if (!cfg->UpdateCFGFreq()) { + MePrediction::RebuildFreq(func, *dom, *meLoop); + } } void BBLayout::LayoutWithProf(bool useChainLayout) { @@ -1346,8 +1349,7 @@ void BBLayout::VerifyBB() { if (bb->GetKind() == kBBCondGoto) { auto *fallthru = bb->GetSucc(0); auto *targetBB = bb->GetSucc(1); - if (fallthru == targetBB || - (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { + if (fallthru == targetBB || (BBEmptyAndFallthru(*fallthru) && (fallthru->GetSucc(0) == targetBB))) { LogInfo::MapleLogger() << "WARN: cond BB " << bb->GetBBId() << " has same target"; } } @@ -1375,11 +1377,15 @@ bool MEBBLayout::PhaseRun(maple::MeFunction &f) { bbLayout->RunLayout(); f.SetLaidOutBBs(bbLayout->GetBBs()); - if (DEBUGFUNC_NEWPM(f)) { + if (DEBUGFUNC_NEWPM(f) || Options::profileUse) { // verify CFG : check condBB's succs should be different bbLayout->VerifyBB(); bbLayout->DumpBBPhyOrder(); - cfg->DumpToFile("afterBBLayout", false); + if (cfg->UpdateCFGFreq() && cfg->DumpIRProfileFile()) { + cfg->DumpToFile("after-bblayout", false, true); + } else { + cfg->DumpToFile("afterBBLayout", false); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index f949ab89fd..f9b88eabae 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -13,30 +13,33 @@ * See the Mulan PSL v2 for more details. */ #include "me_cfg.h" -#include + #include +#include #include + #include "bb.h" -#include "ssa_mir_nodes.h" -#include "me_irmap.h" -#include "mir_builder.h" #include "me_critical_edge.h" +#include "me_irmap.h" #include "me_loop_canon.h" +#include "mir_builder.h" #include "mir_lower.h" +#include "ssa_mir_nodes.h" namespace { constexpr int kFuncNameLenLimit = 80; } namespace maple { -#define MATCH_STMT(stmt, kOpCode) do { \ - while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ - (stmt) = (stmt)->GetNext(); \ - } \ - if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ - return false; \ - } \ -} while (0) // END define +#define MATCH_STMT(stmt, kOpCode) \ + do { \ + while ((stmt) != nullptr && (stmt)->GetOpCode() == OP_comment) { \ + (stmt) = (stmt)->GetNext(); \ + } \ + if ((stmt) == nullptr || (stmt)->GetOpCode() != (kOpCode)) { \ + return false; \ + } \ + } while (0) // END define // determine if need to be replaced by assertnonnull bool MeCFG::IfReplaceWithAssertNonNull(const BB &bb) const { const StmtNode *stmt = bb.GetStmtNodes().begin().d(); @@ -308,7 +311,7 @@ bool MeCFG::FindUse(const StmtNode &stmt, StIdx stIdx) const { return FindExprUse(*iNode.GetRHS(), stIdx); } } - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_eval: case OP_free: case OP_switch: { @@ -511,7 +514,6 @@ void MeCFG::FixMirCFG() { } } - // replace "if() throw NPE()" with assertnonnull void MeCFG::ReplaceWithAssertnonnull() { constexpr char rnnTypeName[] = @@ -682,7 +684,7 @@ void MeCFG::ConvertPhiList2IdentityAssigns(BB &meBB) const { DassignNode *dassign = func.GetMIRModule().GetMIRBuilder()->CreateStmtDassign(*st, ost->GetFieldID(), dread2); func.GetMeSSATab()->GetStmtsSSAPart().SetSSAPartOf( *dassign, func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartMp()->New( - &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); + &func.GetMeSSATab()->GetStmtsSSAPart().GetSSAPartAlloc())); auto *theSSAPart = static_cast(func.GetMeSSATab()->GetStmtsSSAPart().SSAPartOf(*dassign)); theSSAPart->SetSSAVar(*((*phiIt).second.GetResult())); @@ -701,15 +703,15 @@ void MeCFG::ConvertMePhiList2IdentityAssigns(BB &meBB) const { CHECK_FATAL(ost, "ost is nullptr!"); if (ost->IsSymbolOst() && ost->GetIndirectLev() == 0) { MePhiNode *varPhi = phiIt->second; - auto *dassign = func.GetIRMap()->NewInPool( - static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); + auto *dassign = + func.GetIRMap()->NewInPool(static_cast(varPhi->GetLHS()), varPhi->GetOpnd(0)); dassign->SetBB(varPhi->GetDefBB()); dassign->SetIsLive(varPhi->GetIsLive()); meBB.PrependMeStmt(dassign); } else if (ost->IsPregOst()) { MePhiNode *regPhi = phiIt->second; - auto *regAss = func.GetIRMap()->New( - OP_regassign, static_cast(regPhi->GetLHS()), regPhi->GetOpnd(0)); + auto *regAss = func.GetIRMap()->New(OP_regassign, static_cast(regPhi->GetLHS()), + regPhi->GetOpnd(0)); regPhi->GetLHS()->SetDefByStmt(*regAss); regPhi->GetLHS()->SetDefBy(kDefByStmt); regAss->SetBB(regPhi->GetDefBB()); @@ -780,6 +782,10 @@ void MeCFG::WontExitAnalysis() { newBB->SetKindReturn(); newBB->SetAttributes(kBBAttrArtificial); bb->AddSucc(*newBB); + // newBB is added as succ of bb, set freq 0 as its edge frequency + if (updateFreq) { + bb->PushBackSuccFreq(0); + } GetCommonExitBB()->AddExit(*newBB); bb->FindWillExitBBs(currVisitedBBs); // Mark other bbs in the loop as visited. } @@ -836,15 +842,13 @@ void MeCFG::VerifyLabels() const { if (stmtNodes.back().GetOpCode() == OP_throw) { continue; } - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in goto"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in goto"); } else if (mirBB->GetKind() == kBBCondGoto) { - ASSERT( - GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == - static_cast(stmtNodes.back()).GetOffset(), - "undefined label in conditional branch"); + ASSERT(GetLabelBBAt(static_cast(stmtNodes.back()).GetOffset())->GetBBLabel() == + static_cast(stmtNodes.back()).GetOffset(), + "undefined label in conditional branch"); } else if (mirBB->GetKind() == kBBSwitch) { auto &switchStmt = static_cast(stmtNodes.back()); LabelIdx targetLabIdx = switchStmt.GetDefaultLabel(); @@ -967,7 +971,7 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge return; } std::ofstream cfgFile; - std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer + std::streambuf *coutBuf = LogInfo::MapleLogger().rdbuf(); // keep original cout buffer std::streambuf *buf = cfgFile.rdbuf(); LogInfo::MapleLogger().rdbuf(buf); const std::string &fileName = ConstructFileNameToDump(prefix); @@ -981,7 +985,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge if (bIt == common_exit()) { // specical case for common_exit_bb for (auto it = bb->GetPred().begin(); it != bb->GetPred().end(); ++it) { - cfgFile << "BB" << (*it)->GetBBId()<< " -> " << "BB" << bb->GetBBId() << "[style=dotted];\n"; + cfgFile << "BB" << (*it)->GetBBId() << " -> " + << "BB" << bb->GetBBId() << "[style=dotted];\n"; } continue; } @@ -990,7 +995,8 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } for (auto it = bb->GetSucc().begin(); it != bb->GetSucc().end(); ++it) { - cfgFile << "BB" << bb->GetBBId() << " -> " << "BB" << (*it)->GetBBId(); + cfgFile << "BB" << bb->GetBBId() << " -> " + << "BB" << (*it)->GetBBId(); if (bb == GetCommonEntryBB()) { cfgFile << "[style=dotted]"; continue; @@ -1014,20 +1020,19 @@ void MeCFG::DumpToFile(const std::string &prefix, bool dumpInStrs, bool dumpEdge } } if (laidOut != nullptr) { - static std::vector colors = { - "indianred1", "darkorange1", "lightyellow1", "green3", "cyan", "dodgerblue2", "purple2" - }; + static std::vector colors = {"indianred1", "darkorange1", "lightyellow1", "green3", + "cyan", "dodgerblue2", "purple2"}; uint32 colorIdx = 0; size_t clusterSize = laidOut->size() / colors.size(); uint32 cnt = 0; for (uint32 i = 0; i < laidOut->size(); ++i) { auto *bb = (*laidOut)[i]; auto bbId = bb->GetBBId(); - std::string bbNameLabel = dumpEdgeFreq ? - "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) : - "BB" + std::to_string(bbId.GetIdx()); - cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] << ", label=" << - bbNameLabel << "__" << i << "]\n"; + std::string bbNameLabel = + dumpEdgeFreq ? "BB" + std::to_string(bbId.GetIdx()) + "_freq_" + std::to_string(bb->GetFrequency()) + : "BB" + std::to_string(bbId.GetIdx()); + cfgFile << "BB" << bbId << "[style=filled, color=" << colors[colorIdx % colors.size()] + << ", label=" << bbNameLabel << "__" << i << "]\n"; ++cnt; if (cnt > clusterSize) { cnt = 0; @@ -1148,8 +1153,8 @@ bool MeCFG::UnifyRetBBs() { if (func.GetMirFunc()->IsReturnVoid()) { newRetBB->SetFirst(mirBuilder->CreateStmtReturn(nullptr)); } else { - unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", - kStVar, kScAuto, func.GetMirFunc(), kScopeLocal); + unifiedFuncRet = mirBuilder->CreateSymbol(func.GetMirFunc()->GetReturnTyIdx(), "unified_func_ret", kStVar, kScAuto, + func.GetMirFunc(), kScopeLocal); newRetBB->SetFirst(mirBuilder->CreateStmtReturn(mirBuilder->CreateExprDread(*unifiedFuncRet))); } newRetBB->SetLast(newRetBB->GetStmtNodes().begin().d()); @@ -1365,8 +1370,8 @@ void MeCFG::CreateBasicBlocks() { } break; } - // fall thru to handle as return - [[clang::fallthrough]]; + // fall thru to handle as return + [[clang::fallthrough]]; case OP_gosub: case OP_retsub: case OP_return: { @@ -1398,7 +1403,7 @@ void MeCFG::CreateBasicBlocks() { if (!curBB->IsEmpty()) { StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1431,7 +1436,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1462,7 +1467,7 @@ void MeCFG::CreateBasicBlocks() { // prepare a new bb StmtNode *lastStmt = stmt->GetPrev(); ASSERT(curBB->GetStmtNodes().rbegin().base().d() == nullptr || - curBB->GetStmtNodes().rbegin().base().d() == lastStmt, + curBB->GetStmtNodes().rbegin().base().d() == lastStmt, "something wrong building BB"); curBB->SetLast(lastStmt); if (curBB->GetKind() == kBBUnknown) { @@ -1593,7 +1598,7 @@ void MeCFG::CreateBasicBlocks() { } } } while (nextStmt != nullptr); - ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping + ASSERT(tryStmt == nullptr, "unclosed try"); // tryandendtry should be one-one mapping ASSERT(lastTryBB == nullptr, "unclosed tryBB"); // tryandendtry should be one-one mapping auto *lastBB = curBB; if (lastBB->IsEmpty()) { @@ -1623,8 +1628,7 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { if (succ == nullptr) { continue; } - if (inQueue.find(succ) != inQueue.end() || - std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { + if (inQueue.find(succ) != inQueue.end() || std::find(bbs.begin(), bbs.end(), succ) == bbs.end()) { continue; } bool predAllVisited = true; @@ -1652,8 +1656,8 @@ void MeCFG::BBTopologicalSort(SCCOfBBs &scc) { } void MeCFG::BuildSCCDFS(BB &bb, uint32 &visitIndex, std::vector &sccNodes, - std::vector &visitedOrder, std::vector &lowestOrder, - std::vector &inStack, std::stack &visitStack) { + std::vector &visitedOrder, std::vector &lowestOrder, std::vector &inStack, + std::stack &visitStack) { uint32 id = bb.UintID(); visitedOrder[id] = visitIndex; lowestOrder[id] = visitIndex; @@ -1781,7 +1785,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M } } else if (currBB.GetKind() == kBBCondGoto) { if (currBB.GetSucc(0) == &newTarget) { - return; // no need to update offset for fallthru BB + return; // no need to update offset for fallthru BB } BB *gotoBB = currBB.GetSucc().at(1); ASSERT(gotoBB == &newTarget, "[FUNC: %s]newTarget is not one of CondGoto's succ BB", func.GetName().c_str()); @@ -1819,7 +1823,7 @@ void MeCFG::UpdateBranchTarget(BB &currBB, const BB &oldTarget, BB &newTarget, M switchStmt.SetDefaultLabel(label); } for (size_t i = 0; i < switchStmt.GetSwitchTable().size(); ++i) { - LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; + LabelIdx caseLabel = switchStmt.GetSwitchTable().at(i).second; if (caseLabel == oldLabelIdx) { switchStmt.UpdateCaseLabelAt(i, label); } @@ -1876,7 +1880,7 @@ void MeCFG::ConstructEdgeFreqFromBBFreq() { // set bb frequency from stmt record void MeCFG::ConstructBBFreqFromStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1886,13 +1890,14 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { auto eIt = valid_end(); for (auto bIt = valid_begin(); bIt != eIt; ++bIt) { if ((*bIt)->IsEmpty()) continue; - StmtNode& first = (*bIt)->GetFirst(); + StmtNode &first = (*bIt)->GetFirst(); if (funcData->stmtFreqs.count(first.GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[first.GetStmtID()]); } else if (funcData->stmtFreqs.count((*bIt)->GetLast().GetStmtID()) > 0) { (*bIt)->SetFrequency(funcData->stmtFreqs[(*bIt)->GetLast().GetStmtID()]); } else { - LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" << "\n"; + LogInfo::MapleLogger() << "ERROR:: bb " << (*bIt)->GetBBId() << "frequency is not set" + << "\n"; ASSERT(0, "no freq set"); } } @@ -1913,10 +1918,13 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { ConstructEdgeFreqFromBBFreq(); // clear stmtFreqs since cfg frequency is create funcData->stmtFreqs.clear(); + + // set updateFrequency with true + updateFreq = true; } void MeCFG::ConstructStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo *funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } @@ -1927,13 +1935,12 @@ void MeCFG::ConstructStmtFreq() { auto *bb = *bIt; if (bIt == common_entry()) { funcData->entryFreq = bb->GetFrequency(); - funcData->real_entryfreq = funcData->entryFreq; + funcData->realEntryfreq = funcData->entryFreq; } for (auto &stmt : bb->GetStmtNodes()) { Opcode op = stmt.GetOpCode(); // record bb start/end stmt - if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || - stmt.GetStmtID() == bb->GetLast().GetStmtID() || + if (stmt.GetStmtID() == bb->GetFirst().GetStmtID() || stmt.GetStmtID() == bb->GetLast().GetStmtID() || IsCallAssigned(op) || op == OP_call) { funcData->stmtFreqs[stmt.GetStmtID()] = bb->GetFrequency(); } @@ -1943,39 +1950,105 @@ void MeCFG::ConstructStmtFreq() { // bb frequency may be changed in transform phase, // update edgeFreq with new BB frequency by scale -void MeCFG::UpdateEdgeFreqWithNewBBFreq() { - for (size_t idx = 0; idx < bbVec.size(); ++idx) { - BB *currBB = bbVec[idx]; - if (currBB == nullptr || currBB->GetSucc().empty()) { +void MeCFG::UpdateEdgeFreqWithBBFreq() { + BuildSCC(); + for (size_t i = 0; i < GetSccTopologicalVec().size(); ++i) { + SCCOfBBs *scc = GetSccTopologicalVec()[i]; + CHECK_FATAL(scc != nullptr, "scc must not be null"); + if (scc->GetBBs().size() > 1) { + BBTopologicalSort(*scc); + } + const uint32 maxLoopCount = 2; + unsigned loopCount = scc->GetBBs().size() > 1 ? maxLoopCount : 1; + for (unsigned j = 0; j < loopCount; ++j) { + for (BB *bb : scc->GetBBs()) { + if (bb == nullptr) { + continue; + } + // collect pred total except entry + if (!bb->GetAttributes(kBBAttrIsEntry)) { + int64_t inputFreq = 0; + for (auto *pred : bb->GetPred()) { + int idx = pred->GetSuccIndex(*bb); + ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); + inputFreq += pred->GetSuccFreq()[idx]; + } + bb->SetFrequency(inputFreq); + } + // make bb frequency and succs frequency consistent + bb->UpdateEdgeFreqs(false); + } + } + } +} + +void MeCFG::ClearFuncFreqInfo() { + SetUpdateCFGFreq(false); + func.GetMirFunc()->SetFuncProfData(nullptr); + auto &bbVec = GetAllBBs(); + for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit + auto *bb = bbVec[i]; + if (bb == nullptr) { continue; } - // make bb frequency and succs frequency consistent - currBB->UpdateEdgeFreqs(); + bb->SetFrequency(0); + bb->GetSuccFreq().clear(); } } -void MeCFG::VerifyBBFreq() { +// return value is 0 means pass verification, else has problem +int MeCFG::VerifyBBFreq(bool checkFatal) { + int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + ASSERT(entryFreq >= 0, "sanity check"); + bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit auto *bb = bbVec[i]; if (bb == nullptr || bb->GetAttributes(kBBAttrIsEntry) || bb->GetAttributes(kBBAttrIsExit)) { continue; } - // wontexit bb may has wrong succ, skip it + // check case 1: entry count is zero, internal bb has frequency value > 0 + if (entryIsZero && bb->GetFrequency() > 0) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: function entryFreq is zero but internal bb frequency > 0"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } + // check case 2: bb succ frequence numbers should be equal to succ number except wontexit bb + // may has wrong succ, skip it if (bb->GetSuccFreq().size() != bb->GetSucc().size() && !bb->GetAttributes(kBBAttrWontExit)) { - CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + CHECK_FATAL(false, "VerifyBBFreq: succFreq size != succ size"); + } else { + ClearFuncFreqInfo(); + return 1; + } } - // bb freq == sum(out edge freq) + // check case 3: bb freq == sum(out edge freq) uint64 succSumFreq = 0; for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } if (succSumFreq != bb->GetFrequency()) { - LogInfo::MapleLogger() << "[VerifyFreq failure] BB" << bb->GetBBId() << " freq: " << - bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq << std::endl; - LogInfo::MapleLogger() << func.GetName() << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + int diff = succSumFreq - bb->GetFrequency(); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; + } + } } } + return 0; } bool MEMeCfg::PhaseRun(MeFunction &f) { @@ -2009,31 +2082,33 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (!f.GetMIRModule().IsJavaModule() && MeOption::unifyRets) { theCFG->UnifyRetBBs(); } + theCFG->Verify(); // construct bb freq from stmt freq if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { theCFG->ConstructBBFreqFromStmtFreq(); + if (theCFG->DumpIRProfileFile()) { + std::string fileName = "after-mecfgbuild"; + if (f.IsPme()) { + fileName.append("-lfo"); + } else { + fileName.append("-mplme"); + } + theCFG->DumpToFile(fileName, false, true); + } } - theCFG->Verify(); return false; } bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + // if transform pass is not fully support, set disableFreqInfo to true + // function profile information will be deleted after verification phase + bool disableFreqInfo = false; + if (f.GetCfg()->UpdateCFGFreq()) { f.GetCfg()->VerifyBBFreq(); } - // hack code here: no use profile data after verifycation pass since - // following tranform phases related of cfg change are not touched - f.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = f.GetCfg()->GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; - if (bb == nullptr) { - continue; - } - bb->SetFrequency(0); - bb->GetSuccFreq().clear(); - } - + if (!disableFreqInfo) return false; + // clear function profile information + f.GetCfg()->ClearFuncFreqInfo(); return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_critical_edge.cpp b/src/mapleall/maple_me/src/me_critical_edge.cpp index e47078d693..4dca8f82a2 100644 --- a/src/mapleall/maple_me/src/me_critical_edge.cpp +++ b/src/mapleall/maple_me/src/me_critical_edge.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_critical_edge.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" #include "me_function.h" -#include "me_loop_analysis.h" #include "me_irmap.h" +#include "me_loop_analysis.h" +#include "me_option.h" // This phase finds critical edges and split them into two, because their // presence would restrict the optimizations performed by SSAPRE-based phases. @@ -98,8 +100,8 @@ void MeSplitCEdge::UpdateCaseLabel(BB &newBB, MeFunction &func, BB &pred, BB &su } } -void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, - BB &succ, BB *&newBB, bool &isInsertAfterPred) const { +void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, BB &succ, BB *&newBB, + bool &isInsertAfterPred) const { if ((!succ.GetStmtNodes().empty() && succ.GetStmtNodes().front().GetOpCode() == OP_try) || (!succ.IsMeStmtEmpty() && succ.GetFirstMe()->GetOp() == OP_try)) { newBB = &func.GetCfg()->InsertNewBasicBlock(pred, false); @@ -117,8 +119,8 @@ void MeSplitCEdge::DealWithTryBB(const MeFunction &func, BB &pred, void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const { if (isDebugFunc) { - LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << - succ.GetBBId() << "\n"; + LogInfo::MapleLogger() << "******before break : critical edge : BB" << pred.GetBBId() << " -> BB" << succ.GetBBId() + << "\n"; pred.Dump(&func.GetMIRModule()); succ.Dump(&func.GetMIRModule()); } @@ -160,8 +162,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const newBB->SetAttributes(kBBAttrArtificial); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData() && - (!(func.IsPme() || func.IsLfo()))) { + if (cfg->UpdateCFGFreq() && (!(func.IsPme() || func.IsLfo()))) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -189,8 +190,7 @@ void MeSplitCEdge::BreakCriticalEdge(MeFunction &func, BB &pred, BB &succ) const } // profileGen invokes MESplitCEdge to remove critical edges without going through ME completely // newBB needs to be materialized - if (Options::profileGen || - (Options::profileUse && (func.IsPme() || func.IsLfo()))) { + if (Options::profileGen || (Options::profileUse && (func.IsPme() || func.IsLfo()))) { LabelIdx succLabel = succ.GetBBLabel(); ASSERT(succLabel != 0, "succ's label missed"); if (func.GetIRMap() != nullptr) { @@ -306,7 +306,7 @@ bool MESplitCEdge::PhaseRun(maple::MeFunction &f) { mscedge.SplitCriticalEdgeForMeFunc(f); if (Options::profileUse) { if ((f.IsPme() || f.IsLfo()) && f.GetPreMeFunc()) { - // new inserted BB will break while/if label information and IR layout + // new inserted BB break cached while/if label information and IR layout f.GetPreMeFunc()->label2IfInfo.clear(); f.GetPreMeFunc()->label2WhileInfo.clear(); f.GetPreMeFunc()->pmeCreatedIfLabelSet.clear(); diff --git a/src/mapleall/maple_me/src/me_dse.cpp b/src/mapleall/maple_me/src/me_dse.cpp index c2ad027a7e..2d393a9ada 100644 --- a/src/mapleall/maple_me/src/me_dse.cpp +++ b/src/mapleall/maple_me/src/me_dse.cpp @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "me_dse.h" + #include namespace maple { @@ -33,7 +34,7 @@ void MeDSE::VerifyPhi() const { const OriginalSt *ost = func.GetMeSSATab()->GetOriginalStFromID(pair.first); CHECK_FATAL(ost, "ost is nullptr!"); CHECK_FATAL(!ost->IsSymbolOst() || ost->GetIndirectLev() != 0, - "phi is live and non-virtual in bb with zero or one pred"); + "phi is live and non-virtual in bb with zero or one pred"); } else if (pair.second.GetPhiOpnds().size() != predBBNums) { ASSERT(false, "phi opnd num is not consistent with pred bb num(need update phi)"); } @@ -71,8 +72,11 @@ bool MEDse::PhaseRun(maple::MeFunction &f) { f.Verify(); // cfg change , invalid results in MeFuncResultMgr if (dse.UpdatedCfg()) { - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { - f.GetCfg()->UpdateEdgeFreqWithNewBBFreq(); + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile(("after-dse" + std::to_string(f.dseRuns)), false, true); + } } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); } diff --git a/src/mapleall/maple_me/src/me_hdse.cpp b/src/mapleall/maple_me/src/me_hdse.cpp index 6283697dd9..9cc7fa1907 100644 --- a/src/mapleall/maple_me/src/me_hdse.cpp +++ b/src/mapleall/maple_me/src/me_hdse.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_hdse.h" + #include + +#include "hdse.h" +#include "me_ssa.h" #include "ssa_mir_nodes.h" #include "ver_symbol.h" -#include "me_ssa.h" -#include "hdse.h" // The hdse phase performs dead store elimination using the well-known algorithm // based on SSA. The algorithm works as follows: @@ -55,7 +57,7 @@ void MeHDSE::ProcessWhileInfos() { if (preMeFunc == nullptr) { return; } - MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); + MapleMap::iterator it = preMeFunc->label2WhileInfo.begin(); for (; it != preMeFunc->label2WhileInfo.end(); ++it) { if (it->second->initExpr != nullptr && (it->second->initExpr->GetMeOp() == maple::kMeOpVar || it->second->initExpr->GetMeOp() == maple::kMeOpReg)) { @@ -66,7 +68,7 @@ void MeHDSE::ProcessWhileInfos() { void MeHDSE::BackwardSubstitution() { for (DassignMeStmt *dass : backSubsCands) { - ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); + ScalarMeExpr *rhsscalar = static_cast(dass->GetRHS()); if (verstUseCounts[rhsscalar->GetVstIdx()] != 1) { continue; } @@ -110,9 +112,8 @@ void MakeEmptyTrysUnreachable(MeFunction &func) { } BB *endTry = *endTryIt; auto &meStmts = tryBB->GetMeStmts(); - if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && - meStmts.front().GetOp() == OP_try && tryBB->GetMePhiList().empty() && - endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { + if (tryBB->GetAttributes(kBBAttrIsTry) && !meStmts.empty() && meStmts.front().GetOp() == OP_try && + tryBB->GetMePhiList().empty() && endTry->GetAttributes(kBBAttrIsTryEnd) && endTry->IsMeStmtEmpty()) { // we found a try BB followed by an empty endtry BB BB *targetBB = endTry->GetSucc(0); while (!tryBB->GetPred().empty()) { @@ -190,6 +191,7 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MeHDSE hdse = MeHDSE(f, *dom, *hMap, aliasClass, DEBUGFUNC_NEWPM(f)); hdse.hdseKeepRef = MeOption::dseKeepRef; + hdse.SetUpdateFreq(Options::profileUse && f.GetMirFunc()->GetFuncProfData()); if (f.hdseRuns > 2) { hdse.SetRemoveRedefine(true); } @@ -198,6 +200,13 @@ bool MEHdse::PhaseRun(maple::MeFunction &f) { MakeEmptyTrysUnreachable(f); (void)f.GetCfg()->UnreachCodeAnalysis(true); f.GetCfg()->WontExitAnalysis(); + // update frequency + if (hdse.UpdateFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-HDSE" + std::to_string(f.hdseRuns), false, true); + } + } if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "\n============== HDSE =============" << '\n'; f.Dump(false); diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 951da51ee7..05c4b15f8e 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_canon.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -39,8 +41,7 @@ void MeLoopCanon::FindHeadBBs(Dominance &dom, const BB *bb, std::mapGetBBLabel() != 0) { - const MapleUnorderedSet &addrTakenLabels = - func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); + const MapleUnorderedSet &addrTakenLabels = func.GetMirFunc()->GetLabelTab()->GetAddrTakenLabels(); if (addrTakenLabels.find(bb->GetBBLabel()) != addrTakenLabels.end()) { hasIgoto = true; } @@ -71,8 +72,7 @@ void MeLoopCanon::UpdateTheOffsetOfStmtWhenTargetBBIsChange(BB &curBB, const BB static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); - } else if (lastStmt.GetOp() == OP_goto && - static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { + } else if (lastStmt.GetOp() == OP_goto && static_cast(lastStmt).GetOffset() == oldSuccBB.GetBBLabel()) { auto label = func.GetOrCreateBBLabel(newSuccBB); static_cast(lastStmt).SetOffset(label); } else if (lastStmt.GetOp() == OP_switch) { @@ -96,8 +96,19 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, // quick split auto *pred = splitList[0]; auto index = pred->GetSuccIndex(*splittedBB); + // add frequency to mergedBB + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + uint64_t freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(freq); + mergedBB->PushBackSuccFreq(freq); + } splittedBB->ReplacePred(pred, mergedBB); pred->AddSucc(*mergedBB, static_cast(static_cast(index))); + if (updateFreqs) { + pred->AddSuccFreq(mergedBB->GetFrequency(), static_cast(static_cast(index))); + } if (!pred->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*pred, *splittedBB, *mergedBB); } @@ -112,6 +123,7 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, mergedBB->GetMePhiList().emplace(latchLhs->GetOstIdx(), latchPhi); phiIter.second->GetOpnds().push_back(latchLhs); } + uint64_t freq = 0; for (BB *pred : splitList) { auto pos = splittedBB->GetPredIndex(*pred); for (auto &phiIter : mergedBB->GetMePhiList()) { @@ -119,7 +131,17 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, phiIter.second->GetOpnds().push_back(splittedBB->GetMePhiList().at(phiIter.first)->GetOpnd(pos)); } splittedBB->RemovePhiOpnd(pos); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*splittedBB); + ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); + freq = pred->GetEdgeFreq(idx); + mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + } pred->ReplaceSucc(splittedBB, mergedBB); + if (updateFreqs) { + int idx = pred->GetSuccIndex(*mergedBB); + pred->SetSuccFreq(idx, freq); + } if (pred->GetMeStmts().empty()) { continue; } @@ -141,6 +163,9 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, } } splittedBB->AddPred(*mergedBB); + if (updateFreqs) { + mergedBB->PushBackSuccFreq(mergedBB->GetFrequency()); + } isCFGChange = true; } @@ -151,16 +176,14 @@ void MeLoopCanon::Merge(const std::map> &heads) { BB *head = cfg->GetBBFromID(iter->first); // skip case : check latch bb is already added // one pred is preheader bb and the other is latch bb - if ((head->GetPred().size() == 2) && - (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && - (head->GetPred(0)->GetKind() == kBBFallthru) && - (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && + if ((head->GetPred().size() == 2) && (head->GetPred(0)->GetAttributes(kBBAttrArtificial)) && + (head->GetPred(0)->GetKind() == kBBFallthru) && (head->GetPred(1)->GetAttributes(kBBAttrArtificial)) && (head->GetPred(1)->GetKind() == kBBFallthru)) { continue; } auto *latchBB = cfg->NewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop latchBB->SetKind(kBBFallthru); SplitPreds(iter->second, head, latchBB); } @@ -244,8 +267,17 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { BB *newExitBB = cfg->NewBasicBlock(); newExitBB->SetKind(kBBFallthru); auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + freq = curBB->GetSuccFreq()[idx]; + } curBB->ReplaceSucc(succ, newExitBB); succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(freq); + newExitBB->PushBackSuccFreq(freq); + } if (!curBB->GetMeStmts().empty()) { UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } @@ -299,7 +331,8 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { auto *dom = GET_ANALYSIS(MEDominance, f); ASSERT(dom != nullptr, "dom is null in MeDoLoopCanon::Run"); MemPool *loopCanonMp = GetPhaseMemPool(); - auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f)); + bool updateFrequency = (Options::profileUse && f.GetMirFunc()->GetFuncProfData()); + auto *meLoopCanon = loopCanonMp->New(f, DEBUGFUNC_NEWPM(f), updateFrequency); // 1. Add preheaderBB and normalization headBB for loop. meLoopCanon->NormalizationHeadAndPreHeaderOfLoop(*dom); @@ -316,6 +349,9 @@ bool MELoopCanon::PhaseRun(maple::MeFunction &f) { meLoopCanon->NormalizationExitOfLoop(*meLoop); if (meLoopCanon->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); + if (updateFrequency && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopcanon", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index 23a572736d..d3f9505fed 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -13,11 +13,13 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_inversion.h" -#include + #include +#include + #include "me_cfg.h" -#include "me_option.h" #include "me_dominance.h" +#include "me_option.h" #include "me_phase_manager.h" namespace maple { @@ -121,8 +123,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is in loopbody, latchBB need convert condgoto and make original target as its fallthru bool swapSuccOfLatch = (swapSuccs.find(std::make_pair(&bb, &pred)) != swapSuccs.end()); if (isDebugFunc) { - LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " - << pred.GetBBId(); + LogInfo::MapleLogger() << "***loop convert: backedge bb->id " << bb.GetBBId() << " pred->id " << pred.GetBBId(); if (swapSuccOfLatch) { LogInfo::MapleLogger() << " need swap succs\n"; } else { @@ -132,9 +133,9 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapNewBasicBlock(); latchBB->SetAttributes(kBBAttrArtificial); - latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop + latchBB->SetAttributes(kBBAttrIsInLoop); // latchBB is inloop // update newBB frequency : copy predBB succFreq as latch frequency - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { + if (func.GetCfg()->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(bb); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -144,7 +145,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapSetKind(bb.GetKind()); // update succFreq - if (Options::profileUse && func.GetMirFunc()->GetFuncProfData()) { - int succFreqSize = bb.GetSuccFreq().size(); - ASSERT(latchBB->GetSucc().size() == succFreqSize, "sanity check"); - // copy bb succFreq as latch frequency - for (int i = 0; i < succFreqSize; i++) { - latchBB->PushBackSuccFreq(bb.GetSuccFreq()[i]); - } - if (bb.GetFrequency() > 0) { - // swap frequency and fixed the frequency value - if (swapSuccOfLatch) { - ASSERT(latchBB->GetKind() == kBBCondGoto, "impossible"); - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[1] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newtgFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBCondGoto) { - int64_t newftFreq = (latchBB->GetFrequency() == 0 || bb.GetSuccFreq()[0] == 0) ? 0 : 1; - int64_t newtgFreq = latchBB->GetFrequency() == 0 ? 0 : (latchBB->GetFrequency() - newftFreq); - latchBB->SetSuccFreq(0, newftFreq); // freq to exit BB - latchBB->SetSuccFreq(1, newtgFreq); // loop is changed to do-while format - // update bb succ frequency - int64_t bbsucc0Freq = bb.GetSucc(0)->GetFrequency() - newftFreq; - int64_t bbsucc1Freq = bb.GetFrequency() - bbsucc0Freq; - bb.SetSuccFreq(0, bbsucc0Freq); - bb.SetSuccFreq(1, bbsucc1Freq); - } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { - int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; - latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format - bb.SetSuccFreq(0, bb.GetFrequency()); + if (func.GetCfg()->UpdateCFGFreq()) { + if (latchBB->GetKind() == kBBCondGoto) { + BB *succInloop = swapSuccOfLatch ? bb.GetSucc(0) : bb.GetSucc(1); + if ((latchBB->GetFrequency() != 0) && (succInloop->GetFrequency() > 0)) { + // loop is executed + int64_t latchFreq = latchBB->GetFrequency(); + if (swapSuccOfLatch) { + // bb fallthru is in loop, frequency of bb -> exitbb is set 0 + // latchBB fallthru is loop exit + int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { // assume loop body executed only once + bb.SetSuccFreq(0, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(1, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + latchBB->PushBackSuccFreq(0); + } + } else { + // bb->fallthru is loop exit, edge frequency of bb ->exitbb is set 0 + // latchBB fallthru is in loop + int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + if (fallthrudiff >= 0) { + bb.SetSuccFreq(1, bb.GetFrequency()); + bb.SetSuccFreq(0, 0); + latchBB->PushBackSuccFreq(latchFreq - fallthrudiff); + latchBB->PushBackSuccFreq(fallthrudiff); + } else { + bb.SetSuccFreq(1, bb.GetSucc(0)->GetFrequency()); + bb.SetSuccFreq(0, bb.GetFrequency() - bb.GetSucc(0)->GetFrequency()); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(latchBB->GetFrequency()); + } + } } else { - ASSERT(0, "NYI:: unexpected bb type"); + // loop is not executed + if (latchBB->GetFrequency() != 0) { + if (swapSuccOfLatch) { + bb.SetSuccFreq(0, 0); + bb.SetSuccFreq(1, bb.GetFrequency()); + } else { + bb.SetSuccFreq(0, bb.GetFrequency()); + bb.SetSuccFreq(1, 0); + } + } + ASSERT(latchBB->GetFrequency() == 0, "sanity check"); + latchBB->PushBackSuccFreq(0); + latchBB->PushBackSuccFreq(0); } + } else if (latchBB->GetKind() == kBBFallthru || latchBB->GetKind() == kBBGoto) { + int64_t newsuccFreq = (latchBB->GetFrequency() == 0) ? 0 : latchBB->GetSuccFreq()[0] - 1; + latchBB->SetSuccFreq(0, newsuccFreq); // loop is changed to do-while format + bb.SetSuccFreq(0, bb.GetFrequency()); + } else { + ASSERT(0, "NYI:: unexpected bb type"); } } // swap latchBB's succ if needed @@ -332,8 +355,8 @@ void MeLoopInversion::ExecuteLoopInversion(MeFunction &func, Dominance &dom) { } if ((NeedConvert(&func, *succ, *tmpPred, localAlloc, swapSuccs))) { if (isDebugFunc) { - LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() - << " <-- " << tmpPred->GetBBId() << '\n'; + LogInfo::MapleLogger() << "find new backedge " << succ->GetBBId() << " <-- " << tmpPred->GetBBId() + << '\n'; } backEdges.push_back(std::make_pair(succ, tmpPred)); } @@ -362,6 +385,9 @@ bool MELoopInversion::PhaseRun(maple::MeFunction &f) { if (meLoopInversion->IsCFGChange()) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MEDominance::id); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && (f.GetCfg()->DumpIRProfileFile())) { + f.GetCfg()->DumpToFile("after-loopinversion", false, true); + } } return true; } diff --git a/src/mapleall/maple_me/src/me_loop_unrolling.cpp b/src/mapleall/maple_me/src/me_loop_unrolling.cpp index e398584e28..98a5429af0 100644 --- a/src/mapleall/maple_me/src/me_loop_unrolling.cpp +++ b/src/mapleall/maple_me/src/me_loop_unrolling.cpp @@ -13,13 +13,15 @@ * See the Mulan PSL v2 for more details. */ #include "me_loop_unrolling.h" -#include + #include +#include + #include "me_cfg.h" #include "me_option.h" -#include "mir_module.h" -#include "mir_builder.h" #include "me_phase_manager.h" +#include "mir_builder.h" +#include "mir_module.h" namespace maple { bool LoopUnrollingExecutor::enableDebug = false; @@ -36,13 +38,15 @@ bool ProfileCheck(const maple::MeFunction &f) { auto &profile = f.GetMIRModule().GetProfile(); if (!profile.IsValid()) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" << "\n"; + LogInfo::MapleLogger() << "DeCompress failed in loopUnrolling" + << "\n"; } return false; } if (!profile.CheckFuncHot(f.GetName())) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "func is not hot" << "\n"; + LogInfo::MapleLogger() << "func is not hot" + << "\n"; } return false; } @@ -69,12 +73,12 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { case OP_brfalse: case OP_brtrue: case OP_maydassign: - CASE_OP_ASSERT_BOUNDARY { - cost += kTwoInsn; - break; - } + CASE_OP_ASSERT_BOUNDARY { + cost += kTwoInsn; + break; + } case OP_iassign: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_membaracquire: { cost += kThreeInsn; break; @@ -99,7 +103,7 @@ void LoopUnrolling::ComputeCodeSize(const MeStmt &meStmt, uint32 &cost) { } default: if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "consider this op :"<< meStmt.GetOp() << "\n"; + LogInfo::MapleLogger() << "consider this op :" << meStmt.GetOp() << "\n"; } canUnroll = false; break; @@ -152,8 +156,8 @@ void LoopUnrolling::SetLabelWithCondGotoOrGotoBB(BB &bb, std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -174,8 +178,8 @@ void LoopUnrolling::ResetOldLabel2NewLabel(std::unordered_map &old2New } // When loop unroll times more than two, use this function to update the preds and succs of duplicate loopbodys. -void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, - const BB &exitBB, BB &newHeadBB) { +void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2NewBB, BB &bb, const BB &exitBB, + BB &newHeadBB) { if (bb.GetKind() == kBBCondGoto) { CHECK_FATAL(!bb.GetMeStmts().empty(), "must not be empty"); CondGotoMeStmt &condGotoNode = static_cast(bb.GetMeStmts().back()); @@ -194,23 +198,22 @@ void LoopUnrolling::ResetOldLabel2NewLabel2(std::unordered_map &old2Ne } } -void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, - BB &curCopyBB, bool copyAllLoop) { +void LoopUnrolling::ResetFrequency(const BB &curBB, const BB &succ, const BB &exitBB, BB &curCopyBB, bool copyAllLoop) { if (resetFreqForUnrollWithVar && copyAllLoop) { if (&curBB == &exitBB && &succ == *loop->inloopBB2exitBBs.begin()->second->begin()) { curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : 1); } if ((&curBB == loop->latch && &succ == loop->head) || (&curBB == &exitBB && &succ == loop->latch)) { - curCopyBB.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : - loop->head->GetFrequency() % replicatedLoopNum - 1); + curCopyBB.PushBackSuccFreq( + loop->head->GetFrequency() % replicatedLoopNum == 0 ? 0 : loop->head->GetFrequency() % replicatedLoopNum - 1); } else { curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) % replicatedLoopNum); } } else { - profValid && resetFreqForAfterInsertGoto ? - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) : - curBB.GetEdgeFreq(&succ) - 1) : - curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); + profValid &&resetFreqForAfterInsertGoto + ? curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ) - 1 == 0 ? curBB.GetEdgeFreq(&succ) + : curBB.GetEdgeFreq(&succ) - 1) + : curCopyBB.PushBackSuccFreq(curBB.GetEdgeFreq(&succ)); } } @@ -252,10 +255,9 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_mapSetFrequency(succ->GetFrequency() % replicatedLoopNum); } } else { - resetFreqForAfterInsertGoto ? - newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : - succ->GetFrequency() - 1) : - newBB->SetFrequency(succ->GetFrequency()); + resetFreqForAfterInsertGoto + ? newBB->SetFrequency(succ->GetFrequency() - 1 == 0 ? succ->GetFrequency() : succ->GetFrequency() - 1) + : newBB->SetFrequency(succ->GetFrequency()); } curCopyBB->AddSucc(*newBB); ResetFrequency(*curBB, *succ, exitBB, *curCopyBB, copyAllLoop); @@ -272,8 +274,8 @@ void LoopUnrolling::CopyLoopBodyForProfile(BB &newHeadBB, std::unordered_map &old2NewBB, - std::set &labelBBs, const BB &exitBB, bool copyAllLoop) { +void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &old2NewBB, std::set &labelBBs, + const BB &exitBB, bool copyAllLoop) { CreateLableAndInsertLabelBB(newHeadBB, labelBBs); std::queue bbQue; bbQue.push(loop->head); @@ -308,13 +310,13 @@ void LoopUnrolling::CopyLoopBody(BB &newHeadBB, std::unordered_map &ol // Update frequency of old BB. void LoopUnrolling::ResetFrequency(BB &bb) { auto freq = bb.GetFrequency() / replicatedLoopNum; - if (freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && freq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { freq = 1; } bb.SetFrequency(static_cast(freq + partialCount)); for (size_t i = 0; i < bb.GetSucc().size(); ++i) { auto currFreq = bb.GetEdgeFreq(i) / replicatedLoopNum; - if (currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { + if ((!instrumentProf) && currFreq == 0 && partialCount == 0 && bb.GetFrequency() != 0) { currFreq = 1; } bb.SetEdgeFreq(bb.GetSucc(i), currFreq + partialCount); @@ -366,10 +368,10 @@ void LoopUnrolling::AddEdgeForExitBBLastNew2OldBBEmpty(BB &exitBB, std::unordere bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[bb], idx); if (profValid) { - resetFreqForAfterInsertGoto ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + resetFreqForAfterInsertGoto + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[bb]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); } ResetOldLabel2NewLabel(old2NewBB, *bb, exitBB, newHeadBB); } @@ -383,10 +385,10 @@ void LoopUnrolling::AddEdgeForExitBB(BB &exitBB, std::unordered_map &o bb->ReplaceSucc(&exitBB, &newHeadBB); exitBB.AddPred(*old2NewBB[lastNew2OldBB[bb]], idx); if (profValid) { - (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) ? - (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) : - old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); + (resetFreqForAfterInsertGoto && firstResetForAfterInsertGoto) + ? (bb->GetEdgeFreq(idx) - 1 == 0 ? old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx) - 1)) + : old2NewBB[lastNew2OldBB[bb]]->PushBackSuccFreq(bb->GetEdgeFreq(idx)); firstResetForAfterInsertGoto = false; } ResetOldLabel2NewLabel2(old2NewBB, *bb, exitBB, newHeadBB); @@ -403,14 +405,14 @@ void LoopUnrolling::CopyAndInsertBB(bool isPartial) { ResetFrequency(*loop->head); ResetFrequency(); } - profValid && resetFreqForAfterInsertGoto ? - (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) : - newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) : - newHeadBB->SetFrequency(loop->head->GetFrequency()); + profValid &&resetFreqForAfterInsertGoto + ? (loop->head->GetFrequency() - 1 == 0 ? newHeadBB->SetFrequency(loop->head->GetFrequency()) + : newHeadBB->SetFrequency(loop->head->GetFrequency() - 1)) + : newHeadBB->SetFrequency(loop->head->GetFrequency()); (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, false) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, false); if (isPartial) { partialSuccHead = newHeadBB; } @@ -654,7 +656,8 @@ bool LoopUnrolling::LoopPartialUnrollWithConst(uint64 tripCount) { uint32 index = 0; if (!DetermineUnrollTimes(index, true)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "CodeSize is too large" << "\n"; + LogInfo::MapleLogger() << "CodeSize is too large" + << "\n"; } return false; } @@ -710,8 +713,8 @@ void LoopUnrolling::CopyLoopForPartialAndPre(BB *&newHead, BB *&newExiting) { (void)old2NewBB.emplace(loop->head, newHeadBB); std::set labelBBs; resetFreqForUnrollWithVar = true; - profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) : - CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); + profValid ? CopyLoopBodyForProfile(*newHeadBB, old2NewBB, labelBBs, *exitBB, true) + : CopyLoopBody(*newHeadBB, old2NewBB, labelBBs, *exitBB, true); resetFreqForUnrollWithVar = false; for (auto bb : labelBBs) { if (bb->GetKind() == kBBCondGoto) { @@ -742,8 +745,8 @@ VarMeExpr *LoopUnrolling::CreateIndVarOrTripCountWithName(const std::string &nam } // i < tripcount / unrollTime -void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, - MeExpr &unrollTimeExpr, uint32 offset) { +void LoopUnrolling::UpdateCondGotoStmt(BB &bb, VarMeExpr &indVar, MeExpr &tripCount, MeExpr &unrollTimeExpr, + uint32 offset) { for (auto &stmt : bb.GetMeStmts()) { bb.RemoveMeStmt(&stmt); } @@ -815,8 +818,8 @@ void LoopUnrolling::CopyLoopForPartial(BB &partialCondGoto, BB &exitedBB, BB &ex partialCondGoto.AddSucc(*partialHead); if (profValid) { partialCondGoto.PushBackSuccFreq(loop->head->GetFrequency() % replicatedLoopNum); - partialCondGoto.SetFrequency(static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + - partialCondGoto.GetEdgeFreq(1))); + partialCondGoto.SetFrequency( + static_cast(partialCondGoto.GetEdgeFreq(static_cast(0)) + partialCondGoto.GetEdgeFreq(1))); } CHECK_FATAL(partialCondGoto.GetKind() == kBBCondGoto, "must be partialCondGoto"); CHECK_FATAL(!partialCondGoto.GetMeStmts().empty(), "must not be empty"); @@ -976,17 +979,19 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) uint32 index = 0; if (!DetermineUnrollTimes(index, false)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "codesize is too large" << "\n"; + LogInfo::MapleLogger() << "codesize is too large" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with var" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with var" + << "\n"; } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfobeforeLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgbeforeLoopPartialWithVarUnrolling"); } if (!SplitCondGotoBB()) { return false; @@ -1007,8 +1012,8 @@ bool LoopUnrolling::LoopPartialUnrollWithVar(CR &cr, CRNode &varNode, uint32 j) } if (LoopUnrollingExecutor::enableDump) { irMap->Dump(); - profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) : - cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); + profValid ? cfg->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithVarUnrolling", false, true) + : cfg->DumpToFile("cfgafterLoopPartialWithVarUnrolling"); } return true; } @@ -1022,7 +1027,7 @@ void LoopUnrollingExecutor::SetNestedLoop(const IdentifyLoops &meLoop, CHECK_NULL_FATAL(loop->parent); auto it = parentLoop.find(loop->parent); if (it == parentLoop.end()) { - parentLoop[loop->parent] = { loop }; + parentLoop[loop->parent] = {loop}; } else { parentLoop[loop->parent].insert(loop); } @@ -1065,7 +1070,8 @@ bool LoopUnrollingExecutor::PredIsOutOfLoopBB(const MeFunction &func, LoopDesc & return false; } -bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func, LoopDesc &loop, +bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop( + const MeFunction &func, LoopDesc &loop, const std::unordered_map> &parentLoop) const { // Only handle one nested loop. if (parentLoop.find(&loop) != parentLoop.end() && ProfileCheck(func)) { @@ -1083,7 +1089,8 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func CHECK_FATAL(headBB->GetPred().size() == 2, "head must has two preds"); if (!IsDoWhileLoop(func, loop)) { if (enableDebug) { - LogInfo::MapleLogger() << "While-do loop" << "\n"; + LogInfo::MapleLogger() << "While-do loop" + << "\n"; } return false; } @@ -1100,19 +1107,20 @@ bool LoopUnrollingExecutor::IsCanonicalAndOnlyOneExitLoop(const MeFunction &func bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { if (tripCount == kInvalidTripCount) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "tripCount is invalid" << "\n"; + LogInfo::MapleLogger() << "tripCount is invalid" + << "\n"; } return false; } if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "start unrolling with const" << "\n"; + LogInfo::MapleLogger() << "start unrolling with const" + << "\n"; LogInfo::MapleLogger() << "tripCount: " << tripCount << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfobeforLoopUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgbeforLoopUnrolling" + std::to_string(loop->head->GetBBId())); } // fully unroll ReturnKindOfFullyUnroll returnKind = LoopFullyUnroll(static_cast(tripCount)); @@ -1121,13 +1129,14 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } if (returnKind == LoopUnrolling::kCanFullyUnroll) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "fully unrolling" << "\n"; + LogInfo::MapleLogger() << "fully unrolling" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + - std::to_string(loop->head->GetBBId())); + func->IsIRProfValid() + ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopFullyUnrolling", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopFullyUnrolling" + std::to_string(loop->head->GetBBId())); } return true; } @@ -1137,12 +1146,13 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { // partial unroll with const if (LoopPartialUnrollWithConst(tripCount)) { if (LoopUnrollingExecutor::enableDebug) { - LogInfo::MapleLogger() << "partial unrolling with const" << "\n"; + LogInfo::MapleLogger() << "partial unrolling with const" + << "\n"; } if (LoopUnrollingExecutor::enableDebug) { irMap->Dump(); - func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) : - func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); + func->IsIRProfValid() ? func->GetCfg()->DumpToFile("cfgIncludeFreqInfoafterLoopPartialWithConst", false, true) + : func->GetCfg()->DumpToFile("cfgafterLoopPartialWithConstUnrolling"); } return true; } @@ -1150,7 +1160,8 @@ bool LoopUnrolling::LoopUnrollingWithConst(uint64 tripCount, bool onlyFully) { } void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMap, - std::map>> &cands, IdentifyLoops &meLoop, const MapleAllocator &alloc) { + std::map>> &cands, + IdentifyLoops &meLoop, const MapleAllocator &alloc) { if (enableDebug) { LogInfo::MapleLogger() << func.GetName() << "\n"; } @@ -1168,6 +1179,9 @@ void LoopUnrollingExecutor::ExecuteLoopUnrolling(MeFunction &func, MeIRMap &irMa } LoopScalarAnalysisResult sa(irMap, loop); LoopUnrolling loopUnrolling(func, *loop, irMap, alloc, cands); + if (func.GetCfg()->UpdateCFGFreq()) { + loopUnrolling.SetInstrumentProf(true); + } uint64 tripCount = 0; CRNode *conditionCRNode = nullptr; CR *itCR = nullptr; @@ -1236,6 +1250,9 @@ bool MELoopUnrolling::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); + if (f.GetCfg()->UpdateCFGFreq() && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-meloopunroll", false, true); + } } if (DEBUGFUNC_NEWPM(f)) { f.GetCfg()->DumpToFile("afterloopunrolling", false); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 1aa4bc9f5d..0041c51b0d 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -13,10 +13,12 @@ * See the Mulan PSL v2 for more details. */ #include "me_profile_use.h" + #include + #include "me_cfg.h" -#include "me_option.h" #include "me_function.h" +#include "me_option.h" namespace maple { BBUseInfo *MeProfUse::GetOrCreateBBUseInfo(const BB &bb) { @@ -206,8 +208,8 @@ bool MeProfUse::BuildEdgeCount() { uint64 hash = ComputeFuncHash(); if (hash != result.funcHash) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " - << result.funcHash << " func real hash " << hash << '\n'; + LogInfo::MapleLogger() << func->GetName() << " hash doesn't match profile hash " << result.funcHash + << " func real hash " << hash << '\n'; } return false; } @@ -218,8 +220,8 @@ bool MeProfUse::BuildEdgeCount() { } if (instrumentBBs.size() != result.totalCounter) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << result.totalCounter << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << result.totalCounter + << " func real counter " << instrumentBBs.size() << '\n'; } return false; } @@ -294,12 +296,12 @@ bool MeProfUse::Run() { return true; } -GcovFuncInfo *MeProfUse::GetFuncData() { - GcovProfileData *gcovData = func->GetMIRModule().GetGcovProfile(); - if (!gcovData) { +FuncProfInfo *MeProfUse::GetFuncData() { + MplProfileData *profData = func->GetMIRModule().GetMapleProfile(); + if (!profData) { return nullptr; } - GcovFuncInfo *funcData = gcovData->GetFuncProfile(func->GetUniqueID()); + FuncProfInfo *funcData = profData->GetFuncProfile(func->GetUniqueID()); return funcData; } @@ -315,15 +317,15 @@ bool MeProfUse::CheckSumFail(const uint64 hash, const uint32 expectedCheckSum, c return false; } -bool MeProfUse::GcovRun() { - GcovFuncInfo *funcData = GetFuncData(); +bool MeProfUse::MapleProfRun() { + FuncProfInfo *funcData = GetFuncData(); if (!funcData) { return false; } func->GetMirFunc()->SetFuncProfData(funcData); // early return if lineno fail if (CheckSumFail(ComputeLinenoHash(), funcData->linenoChecksum, "lineno")) { - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } FindInstrumentEdges(); @@ -336,12 +338,12 @@ bool MeProfUse::GcovRun() { if (dump) { DumpEdgeInfo(); } - if (instrumentBBs.size() != funcData->numCounts) { + if (instrumentBBs.size() != funcData->edgeCounts) { if (dump) { - LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " - << funcData->numCounts << " func real counter " << instrumentBBs.size() << '\n'; + LogInfo::MapleLogger() << func->GetName() << " counter doesn't match profile counter " << funcData->edgeCounts + << " func real counter " << instrumentBBs.size() << '\n'; } - func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data + func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; } size_t i = 0; @@ -368,16 +370,23 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { MeProfUse profUse(f, *GetPhaseMemPool(), DEBUGFUNC_NEWPM(f)); bool result = true; if (Options::profileUse) { - result = profUse.GcovRun(); - f.GetCfg()->VerifyBBFreq(); + result = profUse.MapleProfRun(); + if (result) { + result = f.GetCfg()->VerifyBBFreq(); + if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; + } + } } else { profUse.Run(); } - if (result) { + if (DEBUGFUNC_NEWPM(f)) { LogInfo::MapleLogger() << "******************after profile use dump function******************\n"; profUse.DumpFuncCFGEdgeFreq(); - f.GetCfg()->DumpToFile("afterProfileUse", false, true); + } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-ProfileUse", false, true); } return true; } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index adafa25a3a..1ac6ba7023 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -93,6 +93,10 @@ void ValueRangePropagation::Execute() { dealWithPhi = true; DealWithPhi(**bIt); dealWithPhi = false; + if (func.GetCfg()->UpdateCFGFreq()) { + // update edge frequency + (*bIt)->UpdateEdgeFreqs(false); + } for (auto it = (*bIt)->GetMeStmts().begin(); it != (*bIt)->GetMeStmts().end();) { bool deleteStmt = false; if (!onlyPropVR) { @@ -3134,9 +3138,20 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB UpdateProfile(*pred, bb, unreachableBB); } Insert2UnreachableBBs(unreachableBB); + // update frequency before cfg changed + int64_t removedFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + int idx = bb.GetSuccIndex(unreachableBB); + removedFreq = bb.GetSuccFreq()[idx]; + } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetSuccFreq(0, bb.GetFrequency()); + succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + unreachableBB.SetFrequency(0); + } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); if (loop == nullptr) { return; @@ -3507,6 +3522,12 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3519,7 +3540,16 @@ void ValueRangePropagation::RemoveUnreachableBB( UpdateProfile(*condGotoBB.GetPred(0), condGotoBB, trueBranch); } condGotoBB.SetKind(kBBFallthru); + int64_t removedFreq = 0; + // update frequency before cfg changed + if (func.GetCfg()->UpdateCFGFreq()) { + removedFreq = condGotoBB.GetSuccFreq()[0]; + } condGotoBB.RemoveSucc(*succ0); + if (func.GetCfg()->UpdateCFGFreq()) { + condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); + succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); } @@ -3677,10 +3707,22 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } return true; } if (CodeSizeIsOverflowOrTheOpOfStmtIsNotSupported(bb)) { @@ -3714,8 +3756,21 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( mergeAllFallthruBBs->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); + if (func.GetCfg()->UpdateCFGFreq()) { + mergeAllFallthruBBs->SetFrequency(edgeFreq); + mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + // update bb frequency + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + } mergeAllFallthruBBs->AddSucc(trueBranch); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); CreateLabelForTargetBB(pred, *mergeAllFallthruBBs); @@ -3780,19 +3835,48 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + // transform may not be consistent with frequency value + updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); if (exitCopyFallthru != nullptr) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + exitCopyFallthru->SetFrequency(edgeFreq); + exitCopyFallthru->PushBackSuccFreq(edgeFreq); + size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); + int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + ASSERT(updatedtrueFreq >= 0, "sanity check"); + bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); + pred.AddSuccFreq(edgeFreq, index); + } return true; } auto *newBB = CreateNewGotoBBWithoutCondGotoStmt(bb); @@ -3806,9 +3890,21 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( newBB->AddMeStmtLast(gotoMeStmt); PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); + int64_t edgeFreq = 0; + if (func.GetCfg()->UpdateCFGFreq()) { + edgeFreq = pred.GetSuccFreq()[index]; + ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); + } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); + if (func.GetCfg()->UpdateCFGFreq()) { + bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.UpdateEdgeFreqs(); + newBB->SetFrequency(edgeFreq); + newBB->PushBackSuccFreq(edgeFreq); + pred.AddSuccFreq(edgeFreq, index); + } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); @@ -5026,6 +5122,13 @@ bool MEValueRangePropagation::PhaseRun(maple::MeFunction &f) { } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &MELoopAnalysis::id); GetAnalysisInfoHook()->ForceRunTransFormPhase(&MELoopCanon::id, f); + // update cfg frequency + if (f.GetCfg()->UpdateCFGFreq()) { + f.GetCfg()->UpdateEdgeFreqWithBBFreq(); + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-valuerange" + std::to_string(f.vrpRuns), false, true); + } + } } // Run vrp twice when need check boundary and nullable pointer. if (MeOption::boundaryCheckMode != kNoCheck || MeOption::npeCheckMode != kNoCheck) { diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index 18092cb1d0..b6cc1f96bf 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -13,8 +13,9 @@ * See the Mulan PSL v2 for more details. */ #include "optimizeCFG.h" -#include "me_phase_manager.h" + #include "factory.h" +#include "me_phase_manager.h" namespace maple { namespace { @@ -23,27 +24,27 @@ std::string funcName; std::string phaseName; #define LOG_BBID(BB) ((BB)->GetBBId().GetIdx()) -#define DEBUG_LOG() if (debug) \ -LogInfo::MapleLogger() << "[" << phaseName << "] " +#define DEBUG_LOG() \ + if (debug) LogInfo::MapleLogger() << "[" << phaseName << "] " // return {trueBB, falseBB} -std::pair GetTrueFalseBrPair(BB *bb) { +std::pair GetTrueFalseBrPair(BB *bb) { if (bb == nullptr) { - return { nullptr, nullptr }; + return {nullptr, nullptr}; } if (bb->GetKind() == kBBCondGoto) { auto *condBr = static_cast(bb->GetLastMe()); CHECK_FATAL(condBr, "condBr is nullptr!"); if (condBr->GetOp() == OP_brtrue) { - return { bb->GetSucc(1), bb->GetSucc(0) }; + return {bb->GetSucc(1), bb->GetSucc(0)}; } else { ASSERT(condBr->GetOp() == OP_brfalse, "only support brtrue/brfalse"); - return { bb->GetSucc(0), bb->GetSucc(1) }; + return {bb->GetSucc(0), bb->GetSucc(1)}; } } else if (bb->GetKind() == kBBGoto) { - return { bb->GetSucc(0), nullptr }; + return {bb->GetSucc(0), nullptr}; } - return { nullptr, nullptr }; + return {nullptr, nullptr}; } // Only one fallthru is allowed for a bb at most , but a bb may have be more than one fallthru pred @@ -82,7 +83,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { if (expr->GetMeOp() == kMeOpConst || expr->GetMeOp() == kMeOpVar) { return; } - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons exprSet.insert(expr); } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -100,7 +101,7 @@ void CollectUnsafeExpr(MeExpr *expr, std::set &exprSet) { // expr not throw exception bool IsSafeExpr(const MeExpr *expr) { - if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons + if (expr->GetMeOp() == kMeOpIvar) { // do not use HasIvar here for efficiency reasons return false; } if (expr->GetOp() == OP_div || expr->GetOp() == OP_rem) { @@ -123,8 +124,7 @@ bool IsSafeExpr(const MeExpr *expr) { bool IsSimpleImm(uint64 imm) { return ((imm & (static_cast(0xffff) << 48u)) == imm) || ((imm & (static_cast(0xffff) << 32u)) == imm) || - ((imm & (static_cast(0xffff) << 16u)) == imm) || - ((imm & (static_cast(0xffff))) == imm) || + ((imm & (static_cast(0xffff) << 16u)) == imm) || ((imm & (static_cast(0xffff))) == imm) || (((~imm) & (static_cast(0xffff) << 48u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 32u)) == ~imm) || (((~imm) & (static_cast(0xffff) << 16u)) == ~imm) || @@ -135,12 +135,12 @@ bool IsSimpleImm(uint64 imm) { // if non-simple imm exist, return it, otherwise return 0 int64 GetNonSimpleImm(MeExpr *expr) { if (expr->GetMeOp() == kMeOpConst && IsPrimitiveInteger(expr->GetPrimType())) { - int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); + int64 imm = static_cast(static_cast(expr)->GetConstVal())->GetExtValue(); if (!IsSimpleImm(static_cast(imm))) { return imm; } } - return 0; // 0 is a simple imm + return 0; // 0 is a simple imm } // Check if ftBB has only one regassign stmt, if regassign exists, return it, otherwise return nullptr @@ -150,7 +150,7 @@ AssignMeStmt *GetSingleAssign(BB *bb) { while (stmt != nullptr && stmt->GetOp() == OP_comment) { stmt = stmt->GetNextMeStmt(); } - if (stmt == nullptr) { // empty bb or has only comment stmt + if (stmt == nullptr) { // empty bb or has only comment stmt return nullptr; } if (stmt->GetOp() == OP_regassign || stmt->GetOp() == OP_dassign) { @@ -193,7 +193,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetPred().empty() && bb->GetSucc().empty() && phiNode.GetOpnds().size() == 1) { @@ -207,7 +207,7 @@ bool IsAllOpndsNotDefByCurrBB(const MeExpr &expr, const BB &currBB, std::setGetBB() != &currBB; } case kMeOpIvar: { - auto &ivar = static_cast(expr); + auto &ivar = static_cast(expr); if (!IsAllOpndsNotDefByCurrBB(*ivar.GetBase(), currBB, infLoopCheck)) { return false; } @@ -249,8 +249,8 @@ bool IsAllOpndsNotDefByCurrBB(const MeStmt &stmt) { MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { if (IsCompareHasReverseOp(cond->GetOp())) { - return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), - *cond->GetOpnd(0), *cond->GetOpnd(1)); + return irmap->CreateMeExprBinary(GetReverseCmpOp(cond->GetOp()), cond->GetPrimType(), *cond->GetOpnd(0), + *cond->GetOpnd(1)); } return irmap->CreateMeExprUnary(OP_lnot, cond->GetPrimType(), *cond); } @@ -258,8 +258,7 @@ MeExpr *GetInvertCond(MeIRMap *irmap, MeExpr *cond) { // Is subSet a subset of superSet? template inline bool IsSubset(const std::set &subSet, const std::set &superSet) { - return std::includes(superSet.begin(), superSet.end(), - subSet.begin(), subSet.end()); + return std::includes(superSet.begin(), superSet.end(), subSet.begin(), subSet.end()); } // before : predCond ---> succCond @@ -269,7 +268,7 @@ bool IsSafeToMergeCond(MeExpr *predCond, MeExpr *succCond) { // Make sure succCond is not dependent on predCond // e.g. if (ptr != nullptr) if (*ptr), the second condition depends on the first one if (predCond == succCond) { - return true; // same expr + return true; // same expr } if (!IsSafeExpr(succCond)) { std::set predSet; @@ -316,9 +315,9 @@ std::unique_ptr GetVRForSimpleCmpExpr(const MeExpr &expr) { if (!IsPrimitiveInteger(opndType)) { return nullptr; } - Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 + Bound opnd1Bound(nullptr, 0, opndType); // bound of expr's opnd1 if (expr.GetOpnd(1)->GetMeOp() == kMeOpConst) { - MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); + MIRConst *constVal = static_cast(expr.GetOpnd(1))->GetConstVal(); if (constVal->GetKind() != kConstInt) { return nullptr; } @@ -380,7 +379,7 @@ BB *GetCommonDest(BB *predBB, BB *succBB) { } if (psucc0 != succBB && psucc1 != succBB) { - return nullptr; // predBB has no branch to succBB + return nullptr; // predBB has no branch to succBB } BB *commonBB = (psucc0 == succBB) ? psucc1 : psucc0; if (commonBB == nullptr) { @@ -517,7 +516,7 @@ bool UnreachBBAnalysis(const maple::MeFunction &f) { } return false; } -} // anonymous namespace +} // anonymous namespace // contains only one valid goto stmt bool HasOnlyMeGotoStmt(BB &bb) { @@ -600,8 +599,8 @@ bool IsMplEmptyBB(BB &bb) { // connectingBB has only one pred and succ, and has no stmt (except a single gotoStmt) in it bool IsConnectingBB(BB &bb) { return (bb.GetPred().size() == 1 && bb.GetSucc().size() == 1) && - (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty - (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty + (IsMeEmptyBB(bb) || HasOnlyMeGotoStmt(bb)) && // for meir, if no meir exist, it is empty + (IsMplEmptyBB(bb) || HasOnlyMplGotoStmt(bb)); // for mplir, if no mplir exist, it is empty } // RealSucc is a non-connecting BB which is not empty (or has just a single gotoStmt). @@ -664,8 +663,8 @@ void EliminateEmptyConnectingBB(const BB *predBB, BB *emptyBB, const BB *stopBB, while (emptyBB != nullptr && emptyBB != stopBB && IsConnectingBB(*emptyBB)) { BB *succ = emptyBB->GetSucc(0); BB *pred = emptyBB->GetPred(0); - DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) - << "(deleted)->BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Delete empty connecting : BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(emptyBB) << "(deleted)->BB" + << LOG_BBID(succ) << "\n"; if (pred->IsPredBB(*succ)) { pred->RemoveSucc(*emptyBB, true); emptyBB->RemoveSucc(*succ, true); @@ -688,27 +687,33 @@ bool HasFallthruPred(const BB &bb) { class OptimizeBB { public: OptimizeBB(BB *bb, MeFunction &func, std::map>> *candidates) - : currBB(bb), f(func), cfg(func.GetCfg()), irmap(func.GetIRMap()), - irBuilder(func.GetMIRModule().GetMIRBuilder()), isMeIR(irmap != nullptr), cands(candidates) {} + : currBB(bb), + f(func), + cfg(func.GetCfg()), + irmap(func.GetIRMap()), + irBuilder(func.GetMIRModule().GetMIRBuilder()), + isMeIR(irmap != nullptr), + cands(candidates) {} // optimize each currBB until no change occur bool OptBBIteratively(); // initial factory to create corresponding optimizer for currBB according to BBKind. void InitBBOptFactory(); private: - BB *currBB = nullptr; // BB we currently perform optimization on - MeFunction &f; // function we currently perform optimization on - MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB - MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt - MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode + BB *currBB = nullptr; // BB we currently perform optimization on + MeFunction &f; // function we currently perform optimization on + MeCFG *cfg = nullptr; // requiring cfg to find pattern to optimize current BB + MeIRMap *irmap = nullptr; // used to create new MeExpr/MeStmt + MIRBuilder *irBuilder = nullptr; // used to create new BaseNode(expr)/StmtNode bool isMeIR = false; - std::map>> *cands = nullptr; // candidates ost need to be updated ssa - std::map> candsOstInBB; // bb with ost needed to be updated - - bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization - // opportunity for currBB after a/some optimization, we should set it true. - // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat { + std::map>> *cands = nullptr; // candidates ost need to be updated ssa + std::map> candsOstInBB; // bb with ost needed to be updated + + bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization + // opportunity for currBB after a/some optimization, we should set it true. + // Otherwise it will stop after all optimizations finished and continue to nextBB. + enum BBErrStat + { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -792,23 +797,23 @@ class OptimizeBB { repeatOpt = false; } #define CHECK_CURR_BB() \ -if (!CheckCurrBB()) { \ - return false; \ -} + if (!CheckCurrBB()) { \ + return false; \ + } #define ONLY_FOR_MEIR() \ -if (!isMeIR) { \ - return false; \ -} + if (!isMeIR) { \ + return false; \ + } }; -using OptBBFatory = FunctionFactory; +using OptBBFatory = FunctionFactory; bool OptimizeBB::CheckCurrBB() { - if (bbErrStat != kBBNoErr) { // has been checked before + if (bbErrStat != kBBNoErr) { // has been checked before return false; } - if (currBB == nullptr) { + if (currBB == nullptr) { bbErrStat = kBBErrNull; return false; } @@ -832,9 +837,9 @@ bool OptimizeBB::CheckCurrBB() { void OptimizeBB::UpdateBBIdInSSACand(const BBId &oldBBID, const BBId &newBBID) { auto it = candsOstInBB.find(oldBBID); if (it == candsOstInBB.end()) { - return; // no item to update + return; // no item to update } - auto &ostSet = candsOstInBB[newBBID]; // find or create + auto &ostSet = candsOstInBB[newBBID]; // find or create ostSet.insert(it->second.begin(), it->second.end()); candsOstInBB.erase(it); for (auto &cand : *cands) { @@ -854,7 +859,7 @@ void OptimizeBB::UpdateSSACandForBBPhiList(BB *bb, const BB *newBB) { if (!isMeIR || bb == nullptr || bb->GetMePhiList().empty()) { return; } - if (newBB == nullptr) { // if not specified, newBB is bb itself + if (newBB == nullptr) { // if not specified, newBB is bb itself newBB = bb; } std::set &ostSet = candsOstInBB[newBB->GetBBId()]; @@ -942,19 +947,18 @@ bool OptimizeBB::BranchBB2UncondBB(BB &bb) { } } - DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") - << "BB" << LOG_BBID(&bb) << " to unconditional BB\n"; + DEBUG_LOG() << "BranchBB2UncondBB : " << (bb.GetKind() == kBBCondGoto ? "Conditional " : "Switch ") << "BB" + << LOG_BBID(&bb) << " to unconditional BB\n"; // delete all empty bb between bb and destBB // note : bb and destBB will be connected after empty BB is deleted for (int i = static_cast(bb.GetSucc().size()) - 1; i >= 0; --i) { EliminateEmptyConnectingBB(&bb, bb.GetSucc(static_cast(i)), destBB, *cfg); } - while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 - ASSERT(bb.GetSucc().back() == destBB, - "[FUNC: %s]Goto BB%d has different destination", funcName.c_str(), LOG_BBID(&bb)); + while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 + ASSERT(bb.GetSucc().back() == destBB, "[FUNC: %s]Goto BB%d has different destination", funcName, LOG_BBID(&bb)); bb.RemoveSucc(*bb.GetSucc().back()); } - if (Options::profileUse && !bb.GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { ASSERT(bb.GetSuccFreq().size() == bb.GetSucc().size(), "sanity check"); bb.SetSuccFreq(0, bb.GetFrequency()); } @@ -1012,30 +1016,32 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { CHECK_FATAL(brStmt, "brStmt is nullptr!"); bool isCondTrue = (!condExpr->IsZero()); bool isBrtrue = (brStmt->GetOp() == OP_brtrue); - if (isCondTrue != isBrtrue) { // goto fallthru BB + if (isCondTrue != isBrtrue) { // goto fallthru BB currBB->RemoveLastMeStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB, true); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { MeStmt *gotoStmt = irmap->CreateGotoMeStmt(f.GetOrCreateBBLabel(*gtBB), currBB, &brStmt->GetSrcPosition()); currBB->ReplaceMeStmt(brStmt, gotoStmt); currBB->SetKind(kBBGoto); // update frequency - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB, true); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1051,25 +1057,27 @@ bool OptimizeBB::OptimizeCondBB2UnCond() { if (isCondTrue != isBrTrue) { currBB->RemoveLastStmt(); currBB->SetKind(kBBFallthru); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[1]; } currBB->RemoveSucc(*gtBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); ftBB->SetFrequency(ftBB->GetFrequency() + removedSuccFreq); + ftBB->UpdateEdgeFreqs(false); } } else { StmtNode *gotoStmt = irBuilder->CreateStmtGoto(OP_goto, f.GetOrCreateBBLabel(*gtBB)); currBB->ReplaceStmt(&brStmt, gotoStmt); currBB->SetKind(kBBGoto); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { removedSuccFreq = currBB->GetSuccFreq()[0]; } currBB->RemoveSucc(*ftBB); - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq()) { currBB->SetSuccFreq(0, currBB->GetFrequency()); gtBB->SetFrequency(gtBB->GetFrequency() + removedSuccFreq); + gtBB->UpdateEdgeFreqs(false); } } SetBBRunAgain(); @@ -1152,11 +1160,15 @@ bool OptimizeBB::RemoveSuccFromNoReturnBB() { if (phiNode->GetOpnds().size() < 1) { break; } - phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum + phiNode->GetOpnds().push_back(phiNode->GetOpnd(0)); // to maintain opnd num and predNum } } (void)EliminateRedundantPhiList(retBB); ResetBBRunAgain(); + // add edge Frequency to exitbb + if (cfg->UpdateCFGFreq()) { + currBB->PushBackSuccFreq(0); + } } return true; } @@ -1210,15 +1222,14 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { } } // update succFreqs before update succs - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData() && - !succ->GetSuccFreq().empty()) { + if (cfg->UpdateCFGFreq() && !succ->GetSuccFreq().empty()) { // copy succFreqs of succ to pred for (int i = 0; i < succ->GetSuccFreq().size(); i++) { pred->PushBackSuccFreq(succ->GetSuccFreq()[i]); } } succ->MoveAllSuccToPred(pred, cfg->GetCommonExitBB()); - pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. + pred->RemoveSucc(*succ, false); // philist will not be associated with pred BB, no need to update phi here. if (!isSuccEmpty) { // only when we move stmt from succ to pred should we set attr and kind here pred->SetAttributes(succ->GetAttributes()); @@ -1242,11 +1253,11 @@ BB *OptimizeBB::MergeSuccIntoPred(BB *pred, BB *succ) { // update bbid : tell ssa-updater to update with new BBID UpdateBBIdInSSACand(succ->GetBBId(), pred->GetBBId()); } - DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) - << ", and delete BB" << LOG_BBID(succ) << "\n"; + DEBUG_LOG() << "Merge BB" << LOG_BBID(succ) << " to BB" << LOG_BBID(pred) << ", and delete BB" << LOG_BBID(succ) + << "\n"; UpdateSSACandForBBPhiList(succ, pred); DeleteBB(succ); - succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. + succ->SetBBId(pred->GetBBId()); // succ has been merged to pred, and reference to succ should be set to pred too. return pred; } @@ -1289,13 +1300,13 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE if (trueExpr == falseExpr) { return true; } - ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName.c_str()) ; - ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName.c_str()) ; + ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName); + ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName); // try to simplify select expr MeExpr *selExpr = irmap->CreateMeExprSelect(trueExpr->GetPrimType(), *condExpr, *trueExpr, *falseExpr); MeExpr *simplifiedSel = irmap->SimplifyMeExpr(selExpr); if (simplifiedSel != selExpr) { - return true; // can be simplified + return true; // can be simplified } // We can check for every opnd of opndExpr, and calculate their cost according to cg's insn @@ -1320,30 +1331,30 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE return true; } - // Ignoring connecting BB, two cases can be turn into select - // condBB condBB - // / \ / \ +// Ignoring connecting BB, two cases can be turn into select +// condBB condBB +// / \ / \ // ftBB gtBB | gtBB/ftBB - // x<- x<- | x<- - // \ / \ / - // jointBB jointBB +// x<- x<- | x<- +// \ / \ / +// jointBB jointBB bool OptimizeBB::CondBranchToSelect() { CHECK_CURR_BB(); - BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB - BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB + BB *ftBB = FindFirstRealSucc(currBB->GetSucc(0)); // fallthruBB + BB *gtBB = FindFirstRealSucc(currBB->GetSucc(1)); // gotoBB if (ftBB == gtBB) { (void)BranchBB2UncondBB(*currBB); return true; } // if ftBB or gtBB itself is jointBB, just return itself; otherwise return real succ - BB *ftTargetBB = (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) - : ftBB; - BB *gtTargetBB = (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) - : gtBB; + BB *ftTargetBB = + (ftBB->GetPred().size() == 1 && ftBB->GetSucc().size() == 1) ? FindFirstRealSucc(ftBB->GetSucc(0)) : ftBB; + BB *gtTargetBB = + (gtBB->GetPred().size() == 1 && gtBB->GetSucc().size() == 1) ? FindFirstRealSucc(gtBB->GetSucc(0)) : gtBB; if (ftTargetBB != gtTargetBB) { return false; } - BB *jointBB = ftTargetBB; // common succ + BB *jointBB = ftTargetBB; // common succ // Check if ftBB has only one assign stmt, set ftStmt if a assign stmt exist AssignMeStmt *ftStmt = nullptr; if (ftBB != jointBB) { @@ -1368,7 +1379,7 @@ bool OptimizeBB::CondBranchToSelect() { // Here we found a pattern, collect select opnds and result reg ScalarMeExpr *ftLHS = nullptr; MeExpr *ftRHS = nullptr; - std::set chiListCands; // collect chilist if assign stmt has one + std::set chiListCands; // collect chilist if assign stmt has one if (ftStmt != nullptr) { ftLHS = static_cast(ftStmt->GetLHS()); ftRHS = ftStmt->GetRHS(); @@ -1416,9 +1427,9 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because two ost assigned are not the same\n"; return false; } - DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) - << ", BB" << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; - if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety + DEBUG_LOG() << "Candidate cond2sel BB" << LOG_BBID(currBB) << "(cond)->{BB" << LOG_BBID(currBB->GetSucc(0)) << ", BB" + << LOG_BBID(currBB->GetSucc(1)) << "}->BB" << LOG_BBID(ftTargetBB) << "(jointBB)\n"; + if (ftRHS != gtRHS) { // if ftRHS is the same as gtRHS, they can be simplified, and no need to check safety // black list if (!IsSafeExpr(ftRHS) || !IsSafeExpr(gtRHS)) { DEBUG_LOG() << "Abort cond2sel for BB" << LOG_BBID(currBB) << ", because trueExpr or falseExpr is not safe\n"; @@ -1437,7 +1448,7 @@ bool OptimizeBB::CondBranchToSelect() { DEBUG_LOG() << "Condition To Select : BB" << LOG_BBID(currBB) << "(cond)->[BB" << LOG_BBID(ftBB) << "(ft), BB" << LOG_BBID(gtBB) << "(gt)]->BB" << LOG_BBID(jointBB) << "(joint)\n"; ScalarMeExpr *resLHS = nullptr; - if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. + if (jointBB->GetPred().size() == 2) { // if jointBB has only ftBB and gtBB as its pred. // use phinode lhs as result auto it = jointBB->GetMePhiList().find(ftLHS->GetOstIdx()); if (it == jointBB->GetMePhiList().end()) { @@ -1451,7 +1462,7 @@ bool OptimizeBB::CondBranchToSelect() { // It is profitable for instruction selection if select opnd is a compare expression // select condExpr, trueExpr, falseExpr => select cmpExpr, trueExpr, falseExpr if (condExpr->IsScalar() && condExpr->GetPrimType() != PTY_u1) { - auto *scalarExpr = static_cast(condExpr); + auto *scalarExpr = static_cast(condExpr); if (scalarExpr->GetDefBy() == kDefByStmt) { MeStmt *defStmt = scalarExpr->GetDefStmt(); MeExpr *rhs = defStmt->GetRHS(); @@ -1476,7 +1487,7 @@ bool OptimizeBB::CondBranchToSelect() { } (void)BranchBB2UncondBB(*currBB); // update phi - if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred + if (jointBB->GetPred().size() == 1) { // jointBB has only currBB as its pred // just remove phinode jointBB->GetMePhiList().erase(resLHS->GetOstIdx()); } else { @@ -1520,11 +1531,11 @@ bool IsExprSameLexicalally(MeExpr *expr1, MeExpr *expr2) { if (const1->GetKind() == kConstInt) { return static_cast(const1)->GetExtValue() == static_cast(const2)->GetExtValue(); } else if (const1->GetKind() == kConstFloatConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } else if (const1->GetKind() == kConstDoubleConst) { - return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), - static_cast(const2)->GetValue()); + return IsFloatingPointNumBitsSame(static_cast(const1)->GetValue(), + static_cast(const2)->GetValue()); } return false; } @@ -1710,18 +1721,18 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { } MeExpr *predCond = predBr->GetOpnd(0); MeExpr *succCond = succBr->GetOpnd(0); - auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false - auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false + auto ptfSucc = GetTrueFalseBrPair(&pred); // pred true and false + auto stfSucc = GetTrueFalseBrPair(&succ); // succ true and false // Try to infer result of succCond from predCond bool isPredTrueBrSucc = (FindFirstRealSucc(ptfSucc.first) == &succ); BranchResult tfBranch = InferSuccCondBrFromPredCond(predCond, succCond, isPredTrueBrSucc); - if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond + if (tfBranch == kBrUnknown) { // succCond cannot be inferred from predCond return false; } // if succ's cond can be inferred from pred's cond, pred can skip succ and branches to newTarget directly BB *newTarget = (tfBranch == kBrTrue) ? FindFirstRealSucc(stfSucc.first) : FindFirstRealSucc(stfSucc.second); if (newTarget == nullptr || newTarget == &succ) { - return false; + return false; } DEBUG_LOG() << "Condition in BB" << LOG_BBID(&succ) << " is redundant, since it has been checked in BB" << LOG_BBID(&pred) << ", BB" << LOG_BBID(&pred) << " can branch to BB" << LOG_BBID(newTarget) << "\n"; @@ -1731,7 +1742,7 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { // succ ... // / \ // ftBB gtBB - if (succ.GetPred().size() == 1) { // succ has only one pred + if (succ.GetPred().size() == 1) { // succ has only one pred // if newTarget is succ's gotoBB, and it has fallthru pred, we should add a goto stmt to succ's last // to replace condGoto stmt. Otherwise, newTarget will have two fallthru pred if (newTarget == FindFirstRealSucc(succ.GetSucc(1)) && HasFallthruPred(*newTarget)) { @@ -1749,7 +1760,17 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { DEBUG_LOG() << "SkipRedundantCond : Remove condBr in BB" << LOG_BBID(&succ) << ", turn it to fallthruBB\n"; } BB *rmBB = (FindFirstRealSucc(succ.GetSucc(0)) == newTarget) ? succ.GetSucc(1) : succ.GetSucc(0); + int64_t deletedSuccFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = succ.GetSuccIndex(*rmBB); + deletedSuccFreq = succ.GetSuccFreq()[idx]; + } succ.RemoveSucc(*rmBB, true); + if (cfg->UpdateCFGFreq()) { + succ.SetSuccFreq(0, succ.GetFrequency()); + auto *succofSucc = succ.GetSucc(0); + succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; } else { @@ -1786,20 +1807,20 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { } BB *replacedSucc = isPredTrueBrSucc ? ptfSucc.first : ptfSucc.second; EliminateEmptyConnectingBB(&pred, replacedSucc, &succ, *cfg); - ASSERT(pred.IsPredBB(succ), - "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName.c_str()); - int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred - pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it + ASSERT(pred.IsPredBB(succ), "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName); + int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred + pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it DEBUG_LOG() << "Replace succ BB" << LOG_BBID(replacedSucc) << " with BB" << LOG_BBID(newBB) << ": BB" - << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" << " => BB" << LOG_BBID(&pred) - << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) << "\n"; + << LOG_BBID(&pred) << "->...->BB" << LOG_BBID(&succ) << "(skipped)" + << " => BB" << LOG_BBID(&pred) << "->BB" << LOG_BBID(newBB) << "(new)->BB" << LOG_BBID(newTarget) + << "\n"; if (pred.GetSucc(1) == newBB) { cfg->UpdateBranchTarget(pred, succ, *newBB, f); } newTarget->AddPred(*newBB); UpdatePhiForMovingPred(predPredIdx, newBB, &succ, newTarget); // update newBB frequency : copy predBB succFreq as newBB frequency - if (Options::profileUse && f.GetMirFunc()->GetFuncProfData()) { + if (cfg->UpdateCFGFreq()) { int idx = pred.GetSuccIndex(*newBB); ASSERT(idx >= 0 && idx < pred.GetSucc().size(), "sanity check"); uint64_t freq = pred.GetEdgeFreq(idx); @@ -1810,6 +1831,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { uint32_t freqOfSucc = succ.GetFrequency(); ASSERT(freqOfSucc >= freq, "sanity check"); succ.SetFrequency(freqOfSucc - freq); + // update edge frequency + BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; + idx = succ.GetSuccIndex(*affectedBB); + ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); + int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + ASSERT(oldedgeFreq >= freq, "sanity check"); + succ.SetSuccFreq(idx, (oldedgeFreq - freq)); } return true; } @@ -1898,7 +1926,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * // create a new version for new phi phiMeNode->SetLHS(irmap->CreateRegOrVarMeExprVersion(ostIdx)); } - UpdateSSACandForBBPhiList(succ); // new philist has been created in succ + UpdateSSACandForBBPhiList(succ); // new philist has been created in succ } else { // succ has other pred besides curr for (auto &phi : succPhiList) { @@ -1929,7 +1957,7 @@ void OptimizeBB::UpdatePhiForMovingPred(int predIdxForCurr, const BB *pred, BB * } else { auto *phiMeNode = irmap->NewInPool(); phiMeNode->SetDefBB(succ); - resPair.first->second = phiMeNode; // replace nullptr inserted before + resPair.first->second = phiMeNode; // replace nullptr inserted before auto &phiOpnds = phiMeNode->GetOpnds(); // insert opnd into New phiNode : all phiOpnds (except for pred) are phiNode lhs in curr phiOpnds.insert(phiOpnds.end(), succ->GetPred().size(), phi.second->GetLHS()); @@ -1968,7 +1996,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (!HasOnlyMeGotoStmt(*succ)) { return false; } - BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB + BB *newTarget = succ->GetSucc(0); // succ must have only one succ, because it is uncondBB if (newTarget == succ) { // succ goto itself, no need to update goto target to newTarget return false; @@ -1980,8 +2008,8 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { // pred is moved to newTarget if (pred->GetKind() == kBBFallthru) { CHECK_FATAL(succ->GetLastMe(), "LastMe is nullptr!"); - GotoMeStmt *gotoMeStmt = irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, - &succ->GetLastMe()->GetSrcPosition()); + GotoMeStmt *gotoMeStmt = + irmap->CreateGotoMeStmt(newTarget->GetBBLabel(), pred, &succ->GetLastMe()->GetSrcPosition()); pred->AddMeStmtLast(gotoMeStmt); pred->SetKind(kBBGoto); DEBUG_LOG() << "Insert Uncond stmt to fallthru BB" << LOG_BBID(currBB) << ", and goto BB" << LOG_BBID(newTarget) @@ -1989,15 +2017,29 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { } int predIdx = succ->GetPredIndex(*pred); bool needUpdatePhi = false; + int64_t removedFreq = 0; + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*succ); + removedFreq = pred->GetSuccFreq()[idx]; + } if (pred->IsPredBB(*newTarget)) { - pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here + if (cfg->UpdateCFGFreq()) { + int idx = pred->GetSuccIndex(*newTarget); + pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + } } else { - pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later + pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later needUpdatePhi = true; } - - DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) - << ": BB" << LOG_BBID(pred) << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; + if (cfg->UpdateCFGFreq()) { + int64_t succFreq = succ->GetFrequency(); + ASSERT(succFreq >= removedFreq, "sanity check"); + succ->SetFrequency(succFreq - removedFreq); + succ->SetSuccFreq(0, succ->GetFrequency()); + } + DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) + << "->BB" << LOG_BBID(succ) << "(merged)->BB" << LOG_BBID(newTarget) << "\n"; cfg->UpdateBranchTarget(*pred, *succ, *newTarget, f); if (needUpdatePhi) { // remove phiOpnd in succ, and add phiOpnd to newTarget @@ -2039,9 +2081,9 @@ bool OptimizeBB::OptimizeUncondBB() { return false; } // wont exit BB and has an edge to commonExit, if we merge it to pred and delete it, the egde will be cut off - if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit - ASSERT(currBB->GetAttributes(kBBAttrWontExit), - "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName.c_str(), LOG_BBID(currBB)); + if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit + ASSERT(currBB->GetAttributes(kBBAttrWontExit), "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName, + LOG_BBID(currBB)); return false; } bool changed = false; @@ -2101,11 +2143,11 @@ bool OptimizeBB::OptimizeSwitchBB() { if (swStmt->GetOpnd()->GetMeOp() != kMeOpConst) { return false; } - auto *swConstExpr = static_cast(swStmt->GetOpnd()); + auto *swConstExpr = static_cast(swStmt->GetOpnd()); MIRConst *swConstVal = swConstExpr->GetConstVal(); ASSERT(swConstVal->GetKind() == kConstInt, "[FUNC: %s]switch is only legal for integer val", funcName.c_str()); int64 val = static_cast(swConstVal)->GetExtValue(); - BB *survivor = currBB->GetSucc(0); // init as default BB + BB *survivor = currBB->GetSucc(0); // init as default BB for (size_t i = 0; i < swStmt->GetSwitchTable().size(); ++i) { int64 caseVal = swStmt->GetSwitchTable().at(i).first; if (caseVal == val) { @@ -2162,8 +2204,8 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { MeExpr *geConst = geExpr->GetOpnd(1); PrimType lePtyp = leConst->GetPrimType(); PrimType gePtyp = geConst->GetPrimType(); - if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || - lePtyp != gePtyp || !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around + if (leConst->GetOp() != OP_constval || geConst->GetOp() != OP_constval || lePtyp != gePtyp || + !IsPrimitiveInteger(lePtyp)) { // only allowed for integer, because float cannot wrap around return nullptr; } int64 leVal = static_cast(static_cast(leConst)->GetConstVal())->GetExtValue(); @@ -2179,9 +2221,9 @@ MeExpr *OptimizeBB::CombineCondByOffset(const MeExpr &expr) { (IsPrimitiveUnsigned(lePtyp) && static_cast(leVal) > static_cast(newGeVal))) { // e.g. x < 3 || x > 2 <==> true return irmap->CreateIntConstMeExpr(1, PTY_u1); - } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 - return irmap->CreateMeExprCompare( - OP_ne, PTY_u1, opndPtyp, *sameExpr, *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); + } else if (leVal == newGeVal) { // e.g. x < 3 || x > 3 <==> x != 3 + return irmap->CreateMeExprCompare(OP_ne, PTY_u1, opndPtyp, *sameExpr, + *irmap->CreateIntConstMeExpr(newGeVal, lePtyp)); } // (x < val1 || x > val2) <==> ((unsigned)(x - val1) > (val2 - val1)) MeExpr *newLeConst = irmap->CreateIntConstMeExpr(leVal, opndPtyp); @@ -2260,15 +2302,15 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { return false; } if (!IsProfitableToMergeCond(predCond, succCond)) { - DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" - << LOG_BBID(succ) << " is not simple enough and not profitable\n"; + DEBUG_LOG() << "Abort Merging Two CondBB : Condition in successor BB" << LOG_BBID(succ) + << " is not simple enough and not profitable\n"; return false; } // Start trying to merge two condition together if possible - auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches - auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches + auto ptfBrPair = GetTrueFalseBrPair(pred); // pred's true and false branches + auto stfBrPair = GetTrueFalseBrPair(succ); // succ's true and false branches Opcode combinedCondOp = OP_undef; - bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) + bool invertSuccCond = false; // invert second condition, e.g. (cond1 && !cond2) // all cases are listed as follow: // | case | predBB -> common | succBB -> common | invertSuccCond | or/and | // | ---- | ---------------- | ---------------- | -------------- | ------ | @@ -2280,16 +2322,16 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // pred's false branch to succ, so true branch to common bool isPredTrueToCommon = (FindFirstRealSucc(ptfBrPair.second) == succ); bool isSuccTrueToCommon = (FindFirstRealSucc(stfBrPair.first) == commonBB); - if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 + if (isPredTrueToCommon && isSuccTrueToCommon) { // case 1 invertSuccCond = false; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 + } else if (!isPredTrueToCommon && !isSuccTrueToCommon) { // case 2 invertSuccCond = false; combinedCondOp = OP_land; - } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 + } else if (isPredTrueToCommon && !isSuccTrueToCommon) { // case 3 invertSuccCond = true; combinedCondOp = OP_lior; - } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 + } else if (!isPredTrueToCommon && isSuccTrueToCommon) { // case 4 invertSuccCond = true; combinedCondOp = OP_land; } else { @@ -2316,7 +2358,7 @@ bool OptimizeBB::FoldBranchToCommonDest(BB *pred, BB *succ) { // remove succ and update cfg BB *exitBB = isSuccTrueToCommon ? stfBrPair.second : stfBrPair.first; pred->ReplaceSucc(succ, exitBB); - exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. + exitBB->RemovePred(*succ, false); // not update phi here, because its phi opnd is the same as before. // we should eliminate edge from succ to commonBB BB *toEliminateBB = isSuccTrueToCommon ? stfBrPair.first : stfBrPair.second; EliminateEmptyConnectingBB(succ, toEliminateBB, commonBB /* stop here */, *cfg); @@ -2359,6 +2401,11 @@ bool OptimizeBB::FoldBranchToCommonDest() { bool OptimizeBB::OptBBOnce() { CHECK_CURR_BB(); DEBUG_LOG() << "Try to optimize BB" << LOG_BBID(currBB) << "...\n"; + // bb frequency may be updated, make bb frequency and succs frequency consistent + // skip deadBB + if (cfg->UpdateCFGFreq() && (!currBB->GetPred().empty()) && (currBB->GetUniquePred() != currBB)) { + currBB->UpdateEdgeFreqs(false); + } bool everChanged = false; // eliminate dead BB : // 1.BB has no pred(expect then entry block) @@ -2421,7 +2468,7 @@ class OptimizeFuntionCFG { private: MeFunction &f; - std::map>> *cands = nullptr; // candidates ost need to update ssa + std::map>> *cands = nullptr; // candidates ost need to update ssa bool OptimizeFuncCFGIteratively(); bool OptimizeCFGForBB(BB *currBB); }; @@ -2444,10 +2491,6 @@ bool OptimizeFuntionCFG::OptimizeFuncCFGIteratively() { if (currBB == nullptr) { continue; } - // bb frequency may be updated, make bb frequency and succs frequency consistent - if (Options::profileUse && !currBB->GetSuccFreq().empty()) { - currBB->UpdateEdgeFreqs(); - } changed |= OptimizeCFGForBB(currBB); } everChanged |= changed; @@ -2493,15 +2536,14 @@ bool OptimizeMeFuncCFG(maple::MeFunction &f, std::mapValidBBNum(); // optimization entry - bool change = OptimizeFuntionCFG(f, ssaCand) - .OptimizeOnFunc(); + bool change = OptimizeFuntionCFG(f, ssaCand).OptimizeOnFunc(); if (change) { f.GetCfg()->WontExitAnalysis(); if (debug) { uint32 bbNumAfter = f.GetCfg()->ValidBBNum(); if (bbNumBefore != bbNumAfter) { - DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") - << " from " << bbNumBefore << " to " << bbNumAfter << "\n"; + DEBUG_LOG() << "BBs' number " << (bbNumBefore > bbNumAfter ? "reduce" : "increase") << " from " << bbNumBefore + << " to " << bbNumAfter << "\n"; } else { DEBUG_LOG() << "BBs' number keep the same as before (num = " << bbNumAfter << ")\n"; } @@ -2522,6 +2564,9 @@ bool MEOptimizeCFGNoSSA::PhaseRun(MeFunction &f) { debug = DEBUGFUNC_NEWPM(f); phaseName = PhaseName(); bool change = OptimizeMeFuncCFG(f, nullptr); + if (change && f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFGNOSSA", false, f.GetCfg()->UpdateCFGFreq()); + } return change; } @@ -2547,7 +2592,10 @@ bool MEOptimizeCFG::PhaseRun(maple::MeFunction &f) { MeSSAUpdate ssaUpdate(f, *f.GetMeSSATab(), *dom, cands); ssaUpdate.Run(); } + if (f.GetCfg()->DumpIRProfileFile()) { + f.GetCfg()->DumpToFile("after-OptimizeCFG", false, f.GetCfg()->UpdateCFGFreq()); + } } return change; } -} // namespace maple +} // namespace maple diff --git a/src/mapleall/maple_util/BUILD.gn b/src/mapleall/maple_util/BUILD.gn index a7341eae06..09f912369e 100755 --- a/src/mapleall/maple_util/BUILD.gn +++ b/src/mapleall/maple_util/BUILD.gn @@ -27,6 +27,7 @@ src_libmplutil = [ "src/error_code.cpp", "src/thread_env.cpp", "src/mpl_int_val.cpp", + "src/mpl_profdata.cpp" ] src_libcommandline = [ diff --git a/src/mapleall/maple_util/include/mpl_profdata.h b/src/mapleall/maple_util/include/mpl_profdata.h new file mode 100644 index 0000000000..23cf6f99b9 --- /dev/null +++ b/src/mapleall/maple_util/include/mpl_profdata.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#define MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#include +#include +#include "mempool_allocator.h" + +namespace maple { +constexpr uint32_t HOTCALLSITEFREQ = 100; +enum UpdateFreqOp { + kKeepOrigFreq = 0, + kUpdateOrigFreq = 0x1, + kUpdateFreqbyScale = 0x2, + kUpdateUnrolledFreq = 0x4, + kUpdateUnrollRemainderFreq = 0x8, +}; + +// used for record cumulative datas +struct ProfileSummaryHistogram { + uint32_t countRatio; + uint32_t startValue; // count value range in [startValue, nextHistogramStart) + uint32_t countNums; // Number of counters whose profile count falls in countValue range. + uint64_t countMinVal; // Smallest profile count included in this range. + uint64_t countCumValue; // Cumulative value of the profile counts + + ProfileSummaryHistogram(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) + : countRatio(0), startValue(s), countNums(num), countMinVal(mincount), countCumValue(cumcounts) {} +}; + +class ProfileSummary { + public: + explicit ProfileSummary(MapleAllocator *alloc) : histogram(alloc->Adapter()) {} + ProfileSummary(MapleAllocator *alloc, uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, + uint64_t sumcount) + : checkSum(checksum), + run(runtimes), + totalCount(totalcount), + maxCount(maxcount), + sumCount(sumcount), + histogram(alloc->Adapter()) {} + + void SetSummary(uint64_t checksum, uint32_t runtimes, uint32_t totalcount, uint64_t maxcount, uint64_t sumcount) { + checkSum = checksum; + run = runtimes; + totalCount = totalcount; + maxCount = maxcount; + sumCount = sumcount; + } + void AddHistogramRecord(uint32_t s, uint32_t num, uint64_t mincount, uint64_t cumcounts) { + histogram.push_back(ProfileSummaryHistogram(s, num, mincount, cumcounts)); + } + void DumpSummary(); + uint64_t GetCheckSum() { + return checkSum; + } + uint32_t GetRun() { + return run; + } + uint32_t GetTotalCount() { + return totalCount; + } + uint64_t GetMaxCount() { + return maxCount; + } + uint64_t GetSumCount() { + return sumCount; + } + uint32_t GetHistogramLength() { + return histogram.size(); + } + void ProcessHistogram(); + MapleVector &GetHistogram() { + return histogram; + } + + private: + uint64_t checkSum; // checksum value of module + uint32_t run; // run times + uint32_t totalCount; // number of counters + uint64_t maxCount; // max counter value in single run + uint64_t sumCount; // sum of all counters accumulated. + MapleVector histogram; // record gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; +}; + +class FuncProfInfo { + public: + FuncProfInfo(MapleAllocator *alloc, unsigned funcIdent, unsigned linenoCs, unsigned cfgCs, unsigned countnum = 0) + : ident(funcIdent), + linenoChecksum(linenoCs), + cfgChecksum(cfgCs), + edgeCounts(countnum), + counts(alloc->Adapter()){}; + ~FuncProfInfo() = default; + + uint64_t GetFuncFrequency() const { + return entryFreq; + } + void SetFuncFrequency(uint64_t freq) { + entryFreq = freq; + } + + uint64_t GetFuncRealFrequency() const { + return realEntryfreq; + } + void SetFuncRealFrequency(uint64_t freq) { + realEntryfreq = freq; + } + + std::unordered_map &GetStmtFreqs() { + return stmtFreqs; + } + uint64_t GetStmtFreq(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + return stmtFreqs[stmtID]; + } + return -1; // unstored + } + void SetStmtFreq(uint32_t stmtID, uint64_t freq) { + stmtFreqs[stmtID] = freq; + } + void EraseStmtFreq(uint32_t stmtID) { + stmtFreqs.erase(stmtID); + } + void CopyStmtFreq(uint32_t newStmtID, uint32_t origStmtId, bool deleteOld = false) { + ASSERT(GetStmtFreq(origStmtId) >= 0, "origStmtId no freq record"); + SetStmtFreq(newStmtID, GetStmtFreq(origStmtId)); + if (deleteOld) { + EraseStmtFreq(origStmtId); + } + } + bool IsHotCallSite(uint32_t stmtID) { + if (stmtFreqs.count(stmtID) > 0) { + uint64_t freq = stmtFreqs[stmtID]; + return (freq >= HOTCALLSITEFREQ); + } + ASSERT(0, "should not be here"); + return false; + } + void DumpFunctionProfile(); + + unsigned ident; + unsigned linenoChecksum; + unsigned cfgChecksum; + + // Raw arc coverage counts. + unsigned edgeCounts; + MapleVector counts; + uint64_t entryFreq; // record entry bb frequence + std::unordered_map stmtFreqs; // stmt_id is key, counter value + uint64_t realEntryfreq; // function prof data may be modified after clone/inline +}; + +class MplProfileData { + public: + MplProfileData(MemPool *m, MapleAllocator *a) : funcsCounter(a->Adapter()), summary(a), mp(m), alloc(a) {} + + FuncProfInfo *GetFuncProfile(unsigned puidx) { + if (funcsCounter.count(puidx) > 0) { + return funcsCounter[puidx]; + } + return nullptr; + } + FuncProfInfo *AddNewFuncProfile(unsigned puidx, unsigned linoCs, unsigned cfgCs, unsigned countnum) { + FuncProfInfo *funcProf = mp->New(alloc, puidx, linoCs, cfgCs, countnum); + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcProf; + return funcProf; + } + void AddFuncProfile(unsigned puidx, FuncProfInfo *funcData) { + ASSERT(funcsCounter.count(puidx) == 0, "sanity check"); + funcsCounter[puidx] = funcData; + } + void DumpProfileData(); + void DumpFunctionsProfile(); + bool IsHotCallSite(uint64_t freq); + + MapleUnorderedMap funcsCounter; // use puidx as key + // record module profile information and statistics of count information + ProfileSummary summary; + uint64_t hotCountThreshold = 0; + + private: + uint64_t GetHotThreshold(); + + MemPool *mp; + MapleAllocator *alloc; +}; +} // namespace maple +#endif // MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index 250e9ef8ba..c3333b16cf 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -190,6 +190,7 @@ static constexpr const char kBindingProtectedRegionStr[] = "__BindingProtectRegi static constexpr const char kClassNamePrefixStr[] = "L"; static constexpr const char kClassMethodSplitterStr[] = "_3B"; static constexpr const char kFuncGetCurrentCl[] = "MCC_GetCurrentClassLoader"; +static constexpr const char kMplProfFileNameExt[] = ".mprofdata"; // Serve as a global flag to indicate whether frequent strings have been compressed extern bool doCompression; @@ -212,6 +213,10 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); } // namespace namemangler #endif diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp new file mode 100644 index 0000000000..849b262239 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ +#include "mpl_profdata.h" + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { +void ProfileSummary::DumpSummary() { + LogInfo::MapleLogger() << "---------ProfileSummary-------------- \n"; + LogInfo::MapleLogger() << " checkSum: " << std::hex << "0x" << checkSum << "\n"; + LogInfo::MapleLogger() << " runtimes: " << std::dec << run << "\n"; + LogInfo::MapleLogger() << " totalCounts: " << std::dec << totalCount << "\n"; + LogInfo::MapleLogger() << " maxCount: " << std::dec << maxCount << "\n"; + LogInfo::MapleLogger() << " count histogram: countRange countNum minCount cumCount \n"; + for (auto &it : histogram) { + LogInfo::MapleLogger() << " " << std::dec << it.startValue << "\t"; + LogInfo::MapleLogger() << std::dec << it.countNums << "\t" << it.countMinVal << "\t" << it.countCumValue << "\n"; + } +} + +void FuncProfInfo::DumpFunctionProfile() { + LogInfo::MapleLogger() << "function ident " << std::dec << ident; + LogInfo::MapleLogger() << " lino_checksum 0x" << std::hex << linenoChecksum << ", "; + LogInfo::MapleLogger() << " cfg_checksum 0x" << std::hex << cfgChecksum << "\n"; + LogInfo::MapleLogger() << " num_counts " << std::dec << edgeCounts << " : "; + for (unsigned i = 0; i < edgeCounts; i++) { + LogInfo::MapleLogger() << std::dec << " " << counts[i]; + } + LogInfo::MapleLogger() << "\n"; +} + +void MplProfileData::DumpFunctionsProfile() { + LogInfo::MapleLogger() << "---------FunctionProfile-------------- \n"; + for (auto &it : funcsCounter) { + it.second->DumpFunctionProfile(); + } +} + +void MplProfileData::DumpProfileData() { + summary.DumpSummary(); + DumpFunctionsProfile(); +} + +void ProfileSummary::ProcessHistogram() { + int countsum = 0; + int n = histogram.size(); + for (int i = n - 1; i >= 0; i--) { + countsum += histogram[i].countNums; + histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + } +} + +#define HOTRATIO 90 +uint64_t MplProfileData::GetHotThreshold() { + for (auto &it : summary.GetHistogram()) { + if (it.countRatio >= HOTRATIO) { + hotCountThreshold = it.startValue; + } else { + if (hotCountThreshold == 0) { + hotCountThreshold = it.countMinVal; // set minValue in currentRange which satisfy hot ratio + } + return hotCountThreshold; + } + } + // should not be here + return 100; +} + +bool MplProfileData::IsHotCallSite(uint64_t freq) { + auto &h = summary.GetHistogram(); + if (hotCountThreshold == 0) { + if (Options::profileHotCountSeted) { + hotCountThreshold = Options::profileHotCount; + } else if (summary.GetTotalCount() > 0 && !h.empty() && h[0].countRatio == 0) { + // init countRatio and compute hotCountThreshold + summary.ProcessHistogram(); + hotCountThreshold = GetHotThreshold(); + } else if (h.empty()) { + // should not be here + ASSERT(0, "should not be here"); + hotCountThreshold = 1; + } + } + return freq >= hotCountThreshold; +} + +} // namespace maple diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index 8e0411bb22..c333420826 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace namemangler { #ifdef __MRT_DEBUG @@ -585,13 +586,111 @@ size_t GetSleb128Size(int32_t v) { int end = ((v >= 0) ? 0 : -1); while (hasMore) { - // judege whether has More valid rem - hasMore = (rem != end) || - ((static_cast(rem) & 1) != (static_cast((static_cast(v) >> 6)) & 1)); + // judege whether has more valid rem + hasMore = (rem != end) || ((static_cast(rem) & 1) != + (static_cast((static_cast(v) >> 6)) & 1)); size++; v = rem; rem >>= static_cast(kGreybackOffset); // intended signed shift: block codedex here } return size; } + +// encode signed to output stream +uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { + bool more; + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + value >>= kGreybackOffset; + more = !((((value == 0) && ((byte & 0x40) == 0)) || + ((value == -1) && ((byte & 0x40) != 0)))); + count++; + if (more) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << static_cast(byte); + } while (more); + return count; +} + +uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { + uint32_t count = 0; + do { + uint8_t byte = value & 0x7f; + value >>= kGreybackOffset; + count++; + if (value != 0) { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + out << char(byte); + } while (value != 0); + return count; +} + +// decode a ULEB128 value. +uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + uint64_t value = 0; + unsigned shift = 0; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + uint64_t slice = *p & 0x7f; + if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value += slice << shift; + shift += kGreybackOffset; + } while (*p++ >= 128); + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + +// decode a SLEB128 value. +int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { + const uint8_t *orig_p = p; + int64_t value = 0; + unsigned shift = 0; + uint8_t byte; + do { + if (p == end) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + byte = *p; + uint64_t slice = byte & 0x7f; + if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || + (shift == 63 && slice != 0 && slice != 0x7f)) { + if (n) { + *n = static_cast(p - orig_p); + } + return 0; + } + value |= slice << shift; + shift += kGreybackOffset; + ++p; + } while (byte >= 128); + // Sign extend negative numbers if needed. + if (shift < 64 && (byte & 0x40)) { + value |= (-1LL) << shift; + } + if (n) { + *n = static_cast(p - orig_p); + } + return value; +} + } // namespace namemangler diff --git a/src/mapleall/mpl2mpl/BUILD.gn b/src/mapleall/mpl2mpl/BUILD.gn index c41431ec49..63ba35bebe 100755 --- a/src/mapleall/mpl2mpl/BUILD.gn +++ b/src/mapleall/mpl2mpl/BUILD.gn @@ -57,7 +57,7 @@ src_libmpl2mpl = [ "src/inline_analyzer.cpp", "src/inline_transformer.cpp", "src/method_replace.cpp", - "src/gcov_parser.cpp", + "src/mpl_profdata_parser.cpp", ] configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] diff --git a/src/mapleall/mpl2mpl/include/gcov_parser.h b/src/mapleall/mpl2mpl/include/gcov_parser.h deleted file mode 100644 index 85dcb3566d..0000000000 --- a/src/mapleall/mpl2mpl/include/gcov_parser.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. - * - * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. - * You can use this software according to the terms and conditions of the MulanPSL - 2.0. - * You may obtain a copy of MulanPSL - 2.0 at: - * - * https://opensource.org/licenses/MulanPSL-2.0 - * - * 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 MulanPSL - 2.0 for more details. - */ - -#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H -#include "mempool.h" -#include "mempool_allocator.h" -#include "bb.h" -#include "maple_phase_manager.h" -#include "gcov_profile.h" - -namespace maple { -using gcov_position_t = unsigned; -// counter defined in gcov-counter.def -enum { - GCOV_COUNTER_ARCS, - GCOV_COUNTER_V_INTERVAL, - GCOV_COUNTER_V_POW2, - GCOV_COUNTER_V_SINGLE, - GCOV_COUNTER_V_INDIR, - GCOV_COUNTER_AVERAGE, - GCOV_COUNTER_IOR, - GCOV_TIME_PROFILER, - GCOV_COUNTER_ICALL_TOPNV, - GCOV_COUNTERS -}; - -class GcovVar { - public: - GcovVar() { - file = nullptr; - buffer = nullptr; - } - FILE *file = nullptr; - gcov_position_t start = 0; - unsigned offset = 0; - unsigned length = 0; - unsigned overread = 0; - int error = 0; - int mode = 0; - int endian = 0; - size_t alloc = 0; - gcov_unsigned_t* buffer = nullptr; -}; - -class MGcovParser : public AnalysisResult { - public: - MGcovParser(MIRModule &mirmod, MemPool *memPool, bool debug) : AnalysisResult(memPool), m(mirmod), - alloc(memPool), localMP(memPool), gcovData(nullptr), dumpDetail(debug) { - gcovVar = localMP->New(); - } - ~MGcovParser() override { - localMP = nullptr; - gcovData = nullptr; - gcovVar = nullptr; - } - int ReadGcdaFile(); - void DumpFuncInfo(); - GcovProfileData *GetGcovData() { return gcovData; } - - private: - using gcov_bucket_type = struct { - gcov_unsigned_t num_counters; - gcov_type min_value; - gcov_type cum_value; - }; - - struct gcov_ctr_summary { - gcov_unsigned_t num; - gcov_unsigned_t runs; - gcov_type sum_all; - gcov_type run_max; - gcov_type sum_max; - gcov_bucket_type histogram[252]; - }; - struct gcov_summary { - gcov_unsigned_t checksum; - struct gcov_ctr_summary ctrs[GCOV_COUNTER_V_INTERVAL]; - }; - - int GcovReadMagic(gcov_unsigned_t magic, gcov_unsigned_t expected); - int GcovOpenFile(const char *name, int mode); - gcov_unsigned_t from_file(gcov_unsigned_t value); - const gcov_unsigned_t *GcovReadWords(unsigned words); - void GcovSync(gcov_position_t base, gcov_unsigned_t length); - int GcovCloseFile(void); - void GcovAllocate(unsigned length); - gcov_unsigned_t GcovReadUnsigned(void); - gcov_position_t GcovGetPosition(void); - gcov_type GcovReadCounter(void); - void GcovReadSummary(struct gcov_summary *summary); - - MIRModule &m; - MapleAllocator alloc; - MemPool *localMP; - GcovProfileData *gcovData; - GcovVar *gcovVar = nullptr; - bool dumpDetail; -}; - -MAPLE_MODULE_PHASE_DECLARE(M2MGcovParser) - -} // end of namespace maple - -#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/include/inline_transformer.h b/src/mapleall/mpl2mpl/include/inline_transformer.h index 8d95a97381..78137411b9 100644 --- a/src/mapleall/mpl2mpl/include/inline_transformer.h +++ b/src/mapleall/mpl2mpl/include/inline_transformer.h @@ -55,7 +55,9 @@ class InlineTransformer { callee(callee), callStmt(callStmt), dumpDetail(dumpDetail), - cg(cg) {} + cg(cg), + updateFreq(Options::profileUse && caller.GetFuncProfData() && callee.GetFuncProfData()){}; + bool PerformInline(BlockNode &enclosingBlk); static void ReplaceSymbols(BaseNode*, uint32, const std::vector*); static void ConvertPStaticToFStatic(MIRFunction &func); @@ -91,6 +93,7 @@ class InlineTransformer { LabelIdx returnLabelIdx = 0; // The lableidx where the code will jump when the callee returns. StmtNode *labelStmt = nullptr; // The LabelNode we created for the callee, if needed. CallGraph *cg = nullptr; + bool updateFreq = false; }; } // namespace maple #endif // MPL2MPL_INCLUDE_INLINE_TRANSFORMER_H diff --git a/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h new file mode 100644 index 0000000000..1a83fa5c83 --- /dev/null +++ b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#ifndef MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#define MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H +#include "bb.h" +#include "maple_phase_manager.h" +#include "mempool.h" +#include "mempool_allocator.h" +#include "mpl_profdata.h" + +namespace maple { +// maple profile data format +// Summary layout +// MagicNumber +// chesum +// run times +// counts number +// count Maxium value +// accumulated count sum +// cout histogram size (count statistic information used for hot function check) +// count lower bound <-- begin of histogram details +// countNum in current range +// minium value in count range +// accumulated count sum +// count range <-- another histogram element +// countNum +// minium value in cout range +// accumulated count sum +// Function profile layout (now only including edge profiling counts) +// function numbers +// function Ident (key number to identify each function(now use mirfunction->puidx) +// function line number checksum +// function cfg checksum +// counts number in function 0 +// count <-- begin of count value +// count +// counts number in function 1 +// count +// ... +// now only unsigned number in profile data, use ULEB128 to encode/decode value for file size + +const uint32_t kMapleProfDataMagicNumber = 0xA0EFEF; + +class ProfDataBinaryImportBase { + public: + ProfDataBinaryImportBase(std::string &filename, std::ifstream &input) : fileName(filename), inputStream(input) {} + template + T ReadNum(); + std::ifstream &GetInputStream() { + return inputStream; + } + std::string &GetProfDataFileName() { + return fileName; + } + void SetPosition(uint8_t *p) { + pos = p; + } + uint8_t *GetPosition() { + return pos; + } + + private: + std::string &fileName; + std::ifstream &inputStream; + uint8_t *pos = nullptr; +}; + +class ProfileSummaryImport : public ProfDataBinaryImportBase { + public: + ProfileSummaryImport(std::string &outputFile, std::ifstream &input) : ProfDataBinaryImportBase(outputFile, input) {} + int ReadSummary(MplProfileData*); + + private: + void ReadMProfMagic(); +}; + +class FunctionProfileImport : public ProfDataBinaryImportBase { + public: + FunctionProfileImport(std::string &inputFile, std::ifstream &input) : ProfDataBinaryImportBase(inputFile, input) {} + int ReadFuncProfile(MplProfileData *profData); +}; + +class MplProfDataParser : public AnalysisResult { + public: + MplProfDataParser(MIRModule &mirmod, MemPool *mp, bool debug) + : AnalysisResult(mp), m(mirmod), alloc(memPool), mempool(mp), dumpDetail(debug) {} + ~MplProfDataParser() = default; + MplProfileData *GetProfData() { + return profData; + } + int ReadMapleProfileData(); + + private: + MIRModule &m; + MapleAllocator alloc; + MemPool *mempool; + MplProfileData *profData = nullptr; + bool dumpDetail = false; +}; + +MAPLE_MODULE_PHASE_DECLARE(MMplProfDataParser) + +} // end of namespace maple + +#endif // MAPLE_MPL2MPL_INCLUDE_GCOVPROFUSE_H diff --git a/src/mapleall/mpl2mpl/src/call_graph.cpp b/src/mapleall/mpl2mpl/src/call_graph.cpp index 449da87d5c..6dd6a88cab 100644 --- a/src/mapleall/mpl2mpl/src/call_graph.cpp +++ b/src/mapleall/mpl2mpl/src/call_graph.cpp @@ -14,7 +14,6 @@ */ #include "call_graph.h" - #include "option.h" #include "retype.h" #include "string_utils.h" @@ -190,7 +189,7 @@ bool CGNode::IsCalleeOf(CGNode *func) const { } uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo->stmtFreqs.count(callstmt->GetStmtID()) > 0) { return funcInfo->stmtFreqs[callstmt->GetStmtID()]; } @@ -199,9 +198,9 @@ uint64_t CGNode::GetCallsiteFrequency(const StmtNode *callstmt) const { } uint64_t CGNode::GetFuncFrequency() const { - GcovFuncInfo *funcInfo = mirFunc->GetFuncProfData(); + FuncProfInfo *funcInfo = mirFunc->GetFuncProfData(); if (funcInfo) { - return funcInfo->GetFuncFrequency(); + return funcInfo->GetFuncRealFrequency(); } ASSERT(0, "should not be here"); return 0; @@ -257,8 +256,8 @@ void CallGraph::DelNode(CGNode &node) { } } -CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, - const KlassHierarchy &kh, const std::string &fn) +CallGraph::CallGraph(MIRModule &m, MemPool &memPool, MemPool &templPool, const KlassHierarchy &kh, + const std::string &fn) : AnalysisResult(&memPool), mirModule(&m), cgAlloc(&memPool), @@ -524,7 +523,7 @@ void CallGraph::RecordLocalConstValue(const StmtNode *stmt) { CallNode *CallGraph::ReplaceIcallToCall(BlockNode &body, IcallNode *icall, PUIdx newPUIdx) { MapleVector opnds(icall->GetNopnd().begin() + 1, icall->GetNopnd().end(), - CurFunction()->GetCodeMPAllocator().Adapter()); + CurFunction()->GetCodeMPAllocator().Adapter()); CallNode *newCall = nullptr; if (icall->GetOpCode() == OP_icall) { newCall = mirBuilder->CreateStmtCall(newPUIdx, opnds, OP_call); @@ -747,8 +746,8 @@ void CallGraph::HandleICall(BlockNode &body, CGNode &node, StmtNode *stmt, uint3 icallToFix.insert({funcType->GetTypeIndex(), tempSet}); } CHECK_FATAL(CurFunction()->GetPuidx() == node.GetPuIdx(), "Error"); - Callsite callSite = { callInfo, node.GetCallee().at(callInfo) }; - icallToFix.at(funcType->GetTypeIndex())->insert({ node.GetPuIdx(), callSite }); + Callsite callSite = {callInfo, node.GetCallee().at(callInfo)}; + icallToFix.at(funcType->GetTypeIndex())->insert({node.GetPuIdx(), callSite}); } void CallGraph::HandleBody(MIRFunction &func, BlockNode &body, CGNode &node, uint32 loopDepth) { @@ -1235,7 +1234,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { Opcode op = stmt->GetOpCode(); switch (op) { case OP_comment: - CASE_OP_ASSERT_NONNULL + CASE_OP_ASSERT_NONNULL case OP_brtrue: case OP_brfalse: case OP_try: @@ -1504,7 +1503,7 @@ void DoDevirtual(const Klass &klass, const KlassHierarchy &klassh) { } } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_call: case OP_callassigned: { CallNode *callNode = static_cast(stmt); @@ -1559,8 +1558,9 @@ void IPODevirtulize::DevirtualFinal() { if (GlobalTables::GetGsymTable().GetSymbolFromStrIdx(classType->GetStaticFieldsGStrIdx(i)) == nullptr) { continue; } - TyIdx tyIdx = GlobalTables::GetGsymTable().GetSymbolFromStrIdx( - classType->GetStaticFieldsPair(i).first)->GetInferredTyIdx(); + TyIdx tyIdx = GlobalTables::GetGsymTable() + .GetSymbolFromStrIdx(classType->GetStaticFieldsPair(i).first) + ->GetInferredTyIdx(); if (tyIdx != kInitTyIdx && tyIdx != kNoneTyIdx) { CHECK_FATAL(attribute.GetAttr(FLDATTR_final), "Must be final private"); if (debugFlag) { @@ -1744,13 +1744,13 @@ void CallGraph::RemoveFileStaticRootNodes() { std::vector staticRoots; std::copy_if(rootNodes.begin(), rootNodes.end(), std::inserter(staticRoots, staticRoots.begin()), [](const CGNode *root) { - // root means no caller, we should also make sure that root is not be used in addroffunc - auto mirFunc = root->GetMIRFunction(); - return root != nullptr && mirFunc != nullptr && // remove before - // if static functions or inline but not extern modified functions are not used anymore, - // they can be removed safely. - !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); - }); + // root means no caller, we should also make sure that root is not be used in addroffunc + auto mirFunc = root->GetMIRFunction(); + return root != nullptr && mirFunc != nullptr && // remove before + // if static functions or inline but not extern modified functions are not used anymore, + // they can be removed safely. + !root->IsAddrTaken() && (mirFunc->IsStatic() || (mirFunc->IsInline() && !mirFunc->IsExtern())); + }); for (auto *root : staticRoots) { // DFS delete root and its callee that is static and have no caller after root is deleted DelNode(*root); diff --git a/src/mapleall/mpl2mpl/src/gen_profile.cpp b/src/mapleall/mpl2mpl/src/gen_profile.cpp index 2f1a0bdb0e..cff72a9561 100644 --- a/src/mapleall/mpl2mpl/src/gen_profile.cpp +++ b/src/mapleall/mpl2mpl/src/gen_profile.cpp @@ -104,9 +104,9 @@ void ProfileGen::CreateModProfDesc() { modProfDescSymMirConst->AddItem(checksumMirConst, 5); // Make the profile file name as fileName.gcda - std::string profFileName = mod.GetProfileDataFileName(); + std::string profFileName = mod.GetProfileDataFileName() + namemangler::kProfFileNameExt; auto *profileFNMirConst = - modMP->New("./" + profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); + modMP->New(profFileName, *GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(PTY_a64))); modProfDescSymMirConst->AddItem(profileFNMirConst, 6); // Additional profiling (in addition to frequency profiling) should be added here diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index 65b2c8d8a9..e0d6984461 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -92,7 +92,7 @@ void MInline::InitParams() { } void MInline::InitProfile() const { - // gcov use different profile data, return + // maple profile use different profile data, return if (Options::profileUse) { return; } @@ -117,7 +117,7 @@ void MInline::InitRCWhiteList() { void MInline::InitExcludedCaller() { std::set specialfunc = { - std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), + std::string("Landroid_2Fcontent_2Fpm_2FFallbackCategoryProvider_3B_7CloadFallbacks_7C_28_29V"), }; for (auto it = specialfunc.begin(); it != specialfunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -140,27 +140,40 @@ void MInline::InitExcludedCallee() { (void)excludedCallee.insert(strIdx); } std::set setArrayHotFunc = { - std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_2FObject_3B_29Ljava_2Flang_2FString_3B"), - std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_29Ljava_2Flang_2FObject_3B"), + std::string("Landroid_2Ficu_2Fimpl_2Fduration_2FBasicDurationFormat_3B_7CformatDuration_7C_28Ljava_2Flang_" + "2FObject_3B_29Ljava_2Flang_2FString_3B"), + std::string("Landroid_2Fapp_2FIActivityManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2Fpm_2FIPackageManager_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Landroid_2Fcontent_2FIContentService_24Stub_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_" + "2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FHwActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_" + "2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Ljava_2Flang_2Freflect_2FMethod_3B_7Cinvoke_7C_28Ljava_2Flang_2FObject_3BALjava_2Flang_2FObject_3B_" + "29Ljava_2Flang_2FObject_3B"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7Crun_7C_28_29V"), - std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), + std::string("Lcom_2Fandroid_2Finternal_2Ftelephony_2FIPhoneStateListener_24Stub_24Proxy_3B_" + "7ConMessageWaitingIndicatorChanged_7C_28Z_29V"), std::string("Landroid_2Fview_2Fanimation_2FTransformation_3B_7C_3Cinit_3E_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartOtherServices_7C_28_29V"), std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FSettings_3B_7CreadLPw_7C_28Ljava_2Futil_2FList_3B_29Z"), std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CupdateOomAdjLocked_7C_28_29V"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_3BLandroid_2Fos_2FParcel_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), - std::string("Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FHwPackageManagerService_3B_7ConTransact_7C_28ILandroid_2Fos_2FParcel_" + "3BLandroid_2Fos_2FParcel_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fpm_2FPackageManagerService_3B_7CgeneratePackageInfo_7C_28Lcom_2Fandroid_" + "2Fserver_2Fpm_2FPackageSetting_3BII_29Landroid_2Fcontent_2Fpm_2FPackageInfo_3B"), + std::string( + "Ljava_2Flang_2FThrowable_3B_7CprintStackTrace_7C_28Ljava_2Flang_2FThrowable_24PrintStreamOrWriter_3B_29V"), std::string("Lcom_2Fandroid_2Fserver_2FSystemServer_3B_7CstartBootstrapServices_7C_28_29V"), std::string("Ljava_2Flang_2FThrowable_3B_7CgetOurStackTrace_7C_28_29ALjava_2Flang_2FStackTraceElement_3B"), std::string("Ldalvik_2Fsystem_2FVMStack_3B_7CgetStackClass2_7C_28_29Ljava_2Flang_2FClass_3B"), - std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_2Fapp_2FIApplicationThread_3BI_29Z"), - std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_2FResultReceiver_3B_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2Fam_2FActivityManagerService_3B_7CattachApplicationLocked_7C_28Landroid_" + "2Fapp_2FIApplicationThread_3BI_29Z"), + std::string("Lcom_2Fandroid_2Fserver_2FInputMethodManagerService_3B_7ChideCurrentInputLocked_7C_28ILandroid_2Fos_" + "2FResultReceiver_3B_29Z"), }; for (auto it = setArrayHotFunc.begin(); it != setArrayHotFunc.end(); ++it) { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(*it); @@ -251,7 +264,7 @@ FuncCostResultType MInline::GetFuncCost(const MIRFunction &func, const BaseNode break; } } - [[clang::fallthrough]]; + [[clang::fallthrough]]; case OP_customcallassigned: case OP_polymorphiccallassigned: case OP_customcall: @@ -421,17 +434,19 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee LogInfo::MapleLogger() << "[CHECK_HOT] " << callee.GetName() << " to " << caller.GetName() << " op " << callStmt.GetOpCode() << '\n'; } - // use gcov profile + // use maple instrument profile if (Options::profileUse) { - return caller.GetFuncProfData()->IsHotCallSite(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) return false; + int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + ASSERT(freq > 0, "sanity check"); + return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); } return module.GetProfile().CheckFuncHot(caller.GetName()); } bool MInline::FuncInlinable(const MIRFunction &func) const { std::string name = func.GetName(); - if (StringUtils::StartsWith(name, kReflectionClassStr) || - StringUtils::StartsWith(name, kJavaLangClassesStr) || + if (StringUtils::StartsWith(name, kReflectionClassStr) || StringUtils::StartsWith(name, kJavaLangClassesStr) || StringUtils::StartsWith(name, kJavaLangReferenceStr)) { return false; } @@ -686,7 +701,7 @@ static InlineResult GetInlineResult(uint32 threshold, uint32 thresholdType, uint } void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction &callee, const CallNode &callStmt, - uint32 &threshold, uint32 &thresholdType) { + uint32 &threshold, uint32 &thresholdType) { // Update threshold if this callsite is hot, or dealing with recursive function if (inlineWithProfile && IsHotCallSite(caller, callee, callStmt)) { threshold = hotFuncThreshold; @@ -705,9 +720,7 @@ void MInline::AdjustInlineThreshold(const MIRFunction &caller, const MIRFunction threshold <<= kRelaxThresholdForInlineHint; } // We don't always inline called_once callee to avoid super big caller - if (module.GetSrcLang() == kSrcLangC && - callee.GetAttr(FUNCATTR_called_once) && - callee.GetAttr(FUNCATTR_static)) { + if (module.GetSrcLang() == kSrcLangC && callee.GetAttr(FUNCATTR_called_once) && callee.GetAttr(FUNCATTR_static)) { threshold <<= kRelaxThresholdForCalledOnce; } } diff --git a/src/mapleall/mpl2mpl/src/inline_transformer.cpp b/src/mapleall/mpl2mpl/src/inline_transformer.cpp index d387f64d29..67a3abc455 100644 --- a/src/mapleall/mpl2mpl/src/inline_transformer.cpp +++ b/src/mapleall/mpl2mpl/src/inline_transformer.cpp @@ -307,7 +307,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s dStmt = builder.CreateStmtRegassign(mirPreg->GetPrimType(), pregIdx, currBaseNode); } dStmt->SetSrcPos(stmt.GetSrcPos()); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(dStmt->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); @@ -315,7 +315,7 @@ GotoNode *InlineTransformer::DoUpdateReturnStmts(BlockNode &newBody, StmtNode &s newBody.ReplaceStmt1WithStmt2(&stmt, dStmt); newBody.InsertAfter(dStmt, gotoNode); } else { - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(gotoNode->GetStmtID(), stmt.GetStmtID()); caller.GetFuncProfData()->EraseStmtFreq(stmt.GetStmtID()); } @@ -458,10 +458,9 @@ BlockNode *InlineTransformer::CloneFuncBody(BlockNode &funcBody, bool recursiveF if (callee.IsFromMpltInline()) { return funcBody.CloneTree(theMIRModule->GetCurFuncCodeMPAllocator()); } - if (Options::profileUse) { + if (updateFreq) { auto *callerProfData = caller.GetFuncProfData(); auto *calleeProfData = callee.GetFuncProfData(); - ASSERT(callerProfData && calleeProfData, "nullptr check"); uint64_t callsiteFreq = callerProfData->GetStmtFreq(callStmt.GetStmtID()); uint64_t calleeEntryFreq = calleeProfData->GetFuncFrequency(); uint32_t updateOp = (kKeepOrigFreq | kUpdateFreqbyScale); @@ -562,7 +561,7 @@ void InlineTransformer::AssignActualsToFormals(BlockNode &newBody, uint32 stIdxO CHECK_NULL_FATAL(currBaseNode); CHECK_NULL_FATAL(formal); AssignActualToFormal(newBody, stIdxOff, regIdxOff, *currBaseNode, *formal); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(newBody.GetFirst()->GetStmtID(), callStmt.GetStmtID()); } } @@ -606,7 +605,7 @@ void InlineTransformer::HandleReturn(BlockNode &newBody) { } } } - if (Options::profileUse && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { + if (updateFreq && (labelStmt != nullptr) && (newBody.GetLast() == labelStmt)) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } @@ -623,7 +622,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne beginCmt += callee.GetName(); StmtNode *commNode = builder.CreateStmtComment(beginCmt.c_str()); enclosingBlk.InsertBefore(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } // end inlining function @@ -639,7 +638,7 @@ void InlineTransformer::ReplaceCalleeBody(BlockNode &enclosingBlk, BlockNode &ne } commNode = builder.CreateStmtComment(endCmt.c_str()); enclosingBlk.InsertAfter(&callStmt, commNode); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(commNode->GetStmtID(), callStmt.GetStmtID()); } CHECK_FATAL(callStmt.GetNext() != nullptr, "null ptr check"); @@ -663,7 +662,7 @@ void InlineTransformer::GenReturnLabel(BlockNode &newBody, uint32 inlinedTimes) // record the created label labelStmt = builder.CreateStmtLabel(returnLabelIdx); newBody.AddStatement(labelStmt); - if (Options::profileUse) { + if (updateFreq) { caller.GetFuncProfData()->CopyStmtFreq(labelStmt->GetStmtID(), callStmt.GetStmtID()); } } diff --git a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp index 375fba0b8d..ff39484443 100644 --- a/src/mapleall/mpl2mpl/src/module_phase_manager.cpp +++ b/src/mapleall/mpl2mpl/src/module_phase_manager.cpp @@ -16,7 +16,7 @@ #include "me_phase_manager.h" #include "ipa_phase_manager.h" #include "ipa_side_effect.h" -#include "gcov_parser.h" +#include "mpl_profdata_parser.h" #define JAVALANG (mirModule.IsJavaModule()) #define CLANG (mirModule.IsCModule()) @@ -109,7 +109,7 @@ MAPLE_ANALYSIS_PHASE_REGISTER(M2MCallGraph, callgraph) MAPLE_ANALYSIS_PHASE_REGISTER(M2MKlassHierarchy, classhierarchy) MAPLE_ANALYSIS_PHASE_REGISTER(M2MAnnotationAnalysis, annotationanalysis) MAPLE_ANALYSIS_PHASE_REGISTER(ProfileGenPM, ProfileGenPM) -MAPLE_ANALYSIS_PHASE_REGISTER(M2MGcovParser, gcovparser) +MAPLE_ANALYSIS_PHASE_REGISTER(MMplProfDataParser, grofDataParser) MAPLE_TRANSFORM_PHASE_REGISTER(M2MInline, inline) MAPLE_TRANSFORM_PHASE_REGISTER(M2MIPODevirtualize, ipodevirtulize) diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp new file mode 100644 index 0000000000..95bd0febdd --- /dev/null +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 v2 for more details. + */ + +#include "mpl_profdata_parser.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpl_logging.h" +#include "option.h" + +namespace maple { + +template +T ProfDataBinaryImportBase::ReadNum() { + unsigned numBytesRead = 0; + uint64_t val = namemangler::DecodeULEB128(pos, &numBytesRead); + + pos += numBytesRead; + return static_cast(val); +} + +int ProfileSummaryImport::ReadSummary(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint64_t magicNum = ReadNum(); + if (magicNum != kMapleProfDataMagicNumber) { + LogInfo::MapleLogger() << "magic number error, quit\n"; + return 1; + } + uint64_t checksum = ReadNum(); + uint32_t runtimes = ReadNum(); + uint32_t numofCounts = ReadNum(); + uint64_t maxCount = ReadNum(); + uint64_t sumCount = ReadNum(); + profData->summary.SetSummary(checksum, runtimes, numofCounts, maxCount, sumCount); + uint32_t veclen = ReadNum(); + + for (uint32_t i = 0; i < veclen; i++) { + uint32_t r1 = ReadNum(); + uint32_t r2 = ReadNum(); + uint64_t r3 = ReadNum(); + uint64_t r4 = ReadNum(); + profData->summary.AddHistogramRecord(r1, r2, r3, r4); + } + + return 0; +} + +int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { + CHECK_FATAL(profData != nullptr, "sanity check"); + uint32_t funcNums = ReadNum(); + if (funcNums == 0) { + return 1; + } + + for (uint32_t i = 0; i < funcNums; i++) { + uint32_t funcIdent = ReadNum(); + uint32_t linocheckSum = ReadNum(); + uint32_t cfgcheckSum = ReadNum(); + uint32_t countNum = ReadNum(); + FuncProfInfo *funcProf = profData->AddNewFuncProfile(funcIdent, linocheckSum, cfgcheckSum, countNum); + CHECK_FATAL(funcProf != nullptr, "nullptr check"); + funcProf->counts.resize(countNum); + for (uint32_t j = 0; j < countNum; j++) { + funcProf->counts[j] = ReadNum(); + } + } + return 0; +} + +int MplProfDataParser::ReadMapleProfileData() { + std::string mprofDataFile = Options::profile; + if (mprofDataFile.empty()) { + if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { + mprofDataFile.append(env_gcovprefix); + if (mprofDataFile.back() != '/') { + mprofDataFile.append("/"); + } + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; + } + uint32_t stripnum = 0; + if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(env_gcovprefixstrip); + stripnum = std::stoi(strip); + if (dumpDetail) { + LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; + } + } + std::string profDataFileName = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "module profdata Name: " << profDataFileName << std::endl; + } + // reduce path in profDataFileName + while (stripnum > 0 && profDataFileName.size() > 1) { + size_t pos = profDataFileName.find_first_of("/", 1); + if (pos == std::string::npos) { + break; + } + profDataFileName = profDataFileName.substr(pos); + stripnum--; + } + if (dumpDetail) { + LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; + } + CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); + mprofDataFile.append(profDataFileName); + } else { + // if gcov_prefix is not set, find .mprofdata according to m.profiledata + mprofDataFile = m.GetProfileDataFileName(); + if (dumpDetail) { + LogInfo::MapleLogger() << "NO ENV, module profdata Name: " << mprofDataFile << std::endl; + } + } + // add .mprofdata + mprofDataFile.append(namemangler::kMplProfFileNameExt); + } + ASSERT(!mprofDataFile.empty(), "null check"); + if (dumpDetail) { + LogInfo::MapleLogger() << "will open mprofileData " << mprofDataFile << std::endl; + } + // create mpl profdata + profData = mempool->New(mempool, &alloc); + // read .mprofdata + std::ifstream inputStream(mprofDataFile, (std::ios::in | std::ios::binary)); + if (!inputStream) { + LogInfo::MapleLogger() << "Could not open the file " << mprofDataFile << "\n"; + return 1; + } + // get length of file + inputStream.seekg(0, std::ios::end); + uint32_t length = inputStream.tellg(); + inputStream.seekg(0, std::ios::beg); + const uint32_t sizeThreshold = 1024 * 10; + CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); + + std::unique_ptr buffer = std::make_unique(length); + inputStream.read(buffer.get(), length); + inputStream.close(); + // read 1st part summary + ProfileSummaryImport summaryImport(mprofDataFile, inputStream); + summaryImport.SetPosition((uint8_t*)(buffer.get())); + int res = summaryImport.ReadSummary(profData); + if (res) { + LogInfo::MapleLogger() << "no summary part\n"; + return 1; + } + if (dumpDetail) { + profData->summary.DumpSummary(); + } + // read 2nd part function profile data + FunctionProfileImport funcImport(mprofDataFile, inputStream); + funcImport.SetPosition(summaryImport.GetPosition()); + res = funcImport.ReadFuncProfile(profData); + if (res) { + LogInfo::MapleLogger() << "no function profile part\n"; + return 1; + } + if (dumpDetail) { + profData->DumpFunctionsProfile(); + } + return 0; +} + +void MMplProfDataParser::GetAnalysisDependence(AnalysisDep &aDep) const { + aDep.SetPreservedAll(); +} + +bool MMplProfDataParser::PhaseRun(maple::MIRModule &m) { + MemPool *memPool = m.GetMemPool(); // use global pool to store profile data + bool enableDebug = true; // true to dump trace + MplProfDataParser parser(m, memPool, enableDebug); + int res = parser.ReadMapleProfileData(); + if (res) { + // something wrong + LogInfo::MapleLogger() << " parse .mprofdata error\n"; + return false; + } + m.SetMapleProfile(parser.GetProfData()); + + return true; +} + +} // end namespace maple -- Gitee From 3958c84aaf8559147bb93953d5a7e39efc84340a Mon Sep 17 00:00:00 2001 From: fye Date: Thu, 11 Aug 2022 08:57:58 -0700 Subject: [PATCH 6/7] profuse: ~170+~60+2 fixes for warnings from CI tools --- src/mapleall/maple_ir/include/mir_module.h | 10 +-- .../maple_me/include/me_loop_unrolling.h | 3 +- src/mapleall/maple_me/src/bb.cpp | 26 +++--- src/mapleall/maple_me/src/hdse.cpp | 11 +-- src/mapleall/maple_me/src/me_cfg.cpp | 50 +++++------ src/mapleall/maple_me/src/me_loop_canon.cpp | 67 +++++++-------- .../maple_me/src/me_loop_inversion.cpp | 4 +- src/mapleall/maple_me/src/me_profile_use.cpp | 4 +- .../maple_me/src/me_value_range_prop.cpp | 83 ++++++++++--------- src/mapleall/maple_me/src/optimizeCFG.cpp | 17 ++-- src/mapleall/maple_util/include/namemangler.h | 2 +- src/mapleall/maple_util/src/mpl_profdata.cpp | 19 +++-- src/mapleall/maple_util/src/namemangler.cpp | 44 +++++----- src/mapleall/mpl2mpl/src/inline.cpp | 6 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 26 +++--- 15 files changed, 190 insertions(+), 182 deletions(-) diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index f5965f008d..700b022338 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -342,12 +342,12 @@ class MIRModule { std::string GetProfileDataFileName() const { std::string profileDataFileName = GetFileName().substr(0, GetFileName().find_last_of(".")); - char *gcov_path = std::getenv("GCOV_PREFIX"); - std::string gcov_prefix = gcov_path ? gcov_path : ""; - if (!gcov_prefix.empty() && (gcov_prefix.back() != '/')) { - gcov_prefix.append("/"); + const char *gcovPath = std::getenv("GCOV_PREFIX"); + std::string gcovPrefix = gcovPath ? gcovPath : ""; + if (!gcovPrefix.empty() && (gcovPrefix.back() != '/')) { + gcovPrefix.append("/"); } - profileDataFileName = gcov_prefix + profileDataFileName; + profileDataFileName = gcovPrefix + profileDataFileName; return profileDataFileName; } diff --git a/src/mapleall/maple_me/include/me_loop_unrolling.h b/src/mapleall/maple_me/include/me_loop_unrolling.h index 1e5f57be8f..fe36d56e73 100644 --- a/src/mapleall/maple_me/include/me_loop_unrolling.h +++ b/src/mapleall/maple_me/include/me_loop_unrolling.h @@ -29,8 +29,7 @@ constexpr uint32 kMaxCost = 100; constexpr uint8 unrollTimes[3] = {8, 4, 2}; // unrollTimes class LoopUnrolling { public: - enum ReturnKindOfFullyUnroll - { + enum ReturnKindOfFullyUnroll { kCanFullyUnroll, kCanNotSplitCondGoto, kCanNotFullyUnroll, diff --git a/src/mapleall/maple_me/src/bb.cpp b/src/mapleall/maple_me/src/bb.cpp index 290a3c6caa..1096c836d9 100644 --- a/src/mapleall/maple_me/src/bb.cpp +++ b/src/mapleall/maple_me/src/bb.cpp @@ -13,9 +13,6 @@ * See the Mulan PSL v2 for more details. */ #include "bb.h" - -#include - #include "me_ir.h" #include "me_ssa.h" #include "mempool_allocator.h" @@ -83,7 +80,8 @@ void BB::DumpBBAttribute(const MIRModule *mod) const { void BB::DumpHeader(const MIRModule *mod) const { mod->GetOut() << "============BB id:" << GetBBId() << " " << StrAttribute() << " ["; DumpBBAttribute(mod); - if (Options::profileUse && frequency >= 0) { + // if (Options::profileUse && frequency >= 0) { + if (Options::profileUse) { mod->GetOut() << " freq: " << frequency << " "; } mod->GetOut() << "]===============\n"; @@ -487,21 +485,19 @@ void BB::UpdateEdgeFreqs(bool updateBBFreqOfSucc) { for (int i = 0; i < len; i++) { succFreqs += GetSuccFreq()[i]; } - int diff = abs(succFreqs - GetFrequency()); - if (len == 0 || diff <= 1) return; - int64_t scaledSum = 0; - for (int i = 0; i < len; i++) { - int64_t sfreq = GetSuccFreq()[i]; + int diff = static_cast(abs(succFreqs - GetFrequency())); + if (len == 0 || diff <= 1) {return;} + for (uint32 i = 0; i < len; i++) { + int64_t sfreq = GetSuccFreq()[static_cast(i)]; int64_t scalefreq = (succFreqs == 0 ? (frequency / len) : (sfreq * frequency / succFreqs)); - scaledSum += scalefreq; - SetSuccFreq(i, scalefreq); + SetSuccFreq(static_cast(i), scalefreq); // update succ frequency with new difference if needed if (updateBBFreqOfSucc) { - auto *succ = GetSucc(i); - int64_t diff = scalefreq - sfreq; - int64_t succBBnewFreq = succ->GetFrequency() + diff; + auto *succBBLoc = GetSucc(static_cast(i)); + int64_t diffFreq = scalefreq - sfreq; + int64_t succBBnewFreq = succBBLoc->GetFrequency() + diffFreq; if (succBBnewFreq >= 0) { - succ->SetFrequency(succBBnewFreq); + succBBLoc->SetFrequency(static_cast(succBBnewFreq)); } } } diff --git a/src/mapleall/maple_me/src/hdse.cpp b/src/mapleall/maple_me/src/hdse.cpp index 99748916e6..52c7360992 100644 --- a/src/mapleall/maple_me/src/hdse.cpp +++ b/src/mapleall/maple_me/src/hdse.cpp @@ -250,11 +250,12 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { } bb.SetKind(kBBFallthru); if (UpdateFreq()) { - int64_t succ0Freq = bb.GetSuccFreq()[0]; + int64_t succ0Freq = static_cast(bb.GetSuccFreq()[0]); bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); ASSERT(bb.GetFrequency() >= succ0Freq, "sanity check"); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + (bb.GetFrequency() - succ0Freq)); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + + (bb.GetFrequency() - succ0Freq))); } } // A ivar contained in stmt @@ -289,7 +290,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // delete the conditional branch BB *succbb = bb.GetSucc().back(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().back(); + removedFreq = static_cast(bb.GetSuccFreq().back()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -302,7 +303,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { // change to unconditional branch BB *succbb = bb.GetSucc().front(); if (UpdateFreq()) { - removedFreq = bb.GetSuccFreq().front(); + removedFreq = static_cast(bb.GetSuccFreq().front()); } succbb->RemoveBBFromPred(bb, false); if (succbb->GetPred().empty()) { @@ -316,7 +317,7 @@ void HDSE::RemoveNotRequiredStmtsInBB(BB &bb) { if (UpdateFreq()) { bb.GetSuccFreq().resize(1); bb.SetSuccFreq(0, bb.GetFrequency()); - bb.GetSucc(0)->SetFrequency(bb.GetSucc(0)->GetFrequency() + removedFreq); + bb.GetSucc(0)->SetFrequency(static_cast(bb.GetSucc(0)->GetFrequency() + removedFreq)); } } else { DetermineUseCounts(condbr->GetOpnd()); diff --git a/src/mapleall/maple_me/src/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index f9b88eabae..1955d9cf38 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -1971,9 +1971,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { for (auto *pred : bb->GetPred()) { int idx = pred->GetSuccIndex(*bb); ASSERT(idx >= 0 && idx < pred->GetSuccFreq().size(), "sanity check"); - inputFreq += pred->GetSuccFreq()[idx]; + inputFreq += static_cast(pred->GetSuccFreq()[static_cast(idx)]); } - bb->SetFrequency(inputFreq); + bb->SetFrequency(static_cast(inputFreq)); } // make bb frequency and succs frequency consistent bb->UpdateEdgeFreqs(false); @@ -1985,9 +1985,9 @@ void MeCFG::UpdateEdgeFreqWithBBFreq() { void MeCFG::ClearFuncFreqInfo() { SetUpdateCFGFreq(false); func.GetMirFunc()->SetFuncProfData(nullptr); - auto &bbVec = GetAllBBs(); - for (size_t i = 0; i < bbVec.size(); ++i) { // skip common entry and common exit - auto *bb = bbVec[i]; + auto &bbVecLoc = GetAllBBs(); + for (size_t i = 0; i < bbVecLoc.size(); ++i) { // skip common entry and common exit + auto *bb = bbVecLoc[i]; if (bb == nullptr) { continue; } @@ -1998,7 +1998,7 @@ void MeCFG::ClearFuncFreqInfo() { // return value is 0 means pass verification, else has problem int MeCFG::VerifyBBFreq(bool checkFatal) { - int64_t entryFreq = func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency(); + int64_t entryFreq = static_cast(func.GetMirFunc()->GetFuncProfData()->GetFuncFrequency()); ASSERT(entryFreq >= 0, "sanity check"); bool entryIsZero = entryFreq == 0 ? true : false; for (size_t i = 2; i < bbVec.size(); ++i) { // skip common entry and common exit @@ -2032,19 +2032,20 @@ int MeCFG::VerifyBBFreq(bool checkFatal) { for (auto succFreq : bb->GetSuccFreq()) { succSumFreq += succFreq; } - if (succSumFreq != bb->GetFrequency()) { - int diff = succSumFreq - bb->GetFrequency(); - diff = diff >= 0 ? diff : -diff; - if (diff > 1) { - if (checkFatal) { - LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; - LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq - << std::endl; - CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); - } else { - ClearFuncFreqInfo(); - return 1; - } + if (succSumFreq == bb->GetFrequency()) { + continue; + } + int64 diff = static_cast(succSumFreq - bb->GetFrequency()); + diff = diff >= 0 ? diff : -diff; + if (diff > 1) { + if (checkFatal) { + LogInfo::MapleLogger() << func.GetName() << "wrong BB " << bb->GetBBId() << std::endl; + LogInfo::MapleLogger() << " freq: " << bb->GetFrequency() << ", all succ edge freq sum: " << succSumFreq + << std::endl; + CHECK_FATAL(false, "VerifyFreq failure: bb freq != succ freq sum"); + } else { + ClearFuncFreqInfo(); + return 1; } } } @@ -2089,9 +2090,9 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { if (theCFG->DumpIRProfileFile()) { std::string fileName = "after-mecfgbuild"; if (f.IsPme()) { - fileName.append("-lfo"); + static_cast(fileName.append("-lfo")); } else { - fileName.append("-mplme"); + static_cast(fileName.append("-mplme")); } theCFG->DumpToFile(fileName, false, true); } @@ -2102,13 +2103,14 @@ bool MEMeCfg::PhaseRun(MeFunction &f) { bool MECfgVerifyFrequency::PhaseRun(MeFunction &f) { // if transform pass is not fully support, set disableFreqInfo to true // function profile information will be deleted after verification phase - bool disableFreqInfo = false; if (f.GetCfg()->UpdateCFGFreq()) { - f.GetCfg()->VerifyBBFreq(); + static_cast(f.GetCfg()->VerifyBBFreq()); } - if (!disableFreqInfo) return false; +#ifdef disableFreqInfo + //if (!disableFreqInfo) {return falsea}; // clear function profile information f.GetCfg()->ClearFuncFreqInfo(); +#endif return false; } } // namespace maple diff --git a/src/mapleall/maple_me/src/me_loop_canon.cpp b/src/mapleall/maple_me/src/me_loop_canon.cpp index 05c4b15f8e..e3f4c6e15d 100644 --- a/src/mapleall/maple_me/src/me_loop_canon.cpp +++ b/src/mapleall/maple_me/src/me_loop_canon.cpp @@ -100,8 +100,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - uint64_t freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(freq); + uint64_t freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(freq)); mergedBB->PushBackSuccFreq(freq); } splittedBB->ReplacePred(pred, mergedBB); @@ -134,8 +134,8 @@ void MeLoopCanon::SplitPreds(const std::vector &splitList, BB *splittedBB, if (updateFreqs) { int idx = pred->GetSuccIndex(*splittedBB); ASSERT(idx >= 0 && idx < pred->GetSucc().size(), "sanity check"); - freq = pred->GetEdgeFreq(idx); - mergedBB->SetFrequency(mergedBB->GetFrequency() + freq); + freq = pred->GetEdgeFreq(static_cast(idx)); + mergedBB->SetFrequency(static_cast(mergedBB->GetFrequency() + freq)); } pred->ReplaceSucc(splittedBB, mergedBB); if (updateFreqs) { @@ -254,38 +254,39 @@ void MeLoopCanon::InsertExitBB(LoopDesc &loop) { if (loop.Has(*succ)) { inLoopBBs.push(succ); traveledBBs.insert(succ); - } else { - bool needNewExitBB = false; - for (auto pred : succ->GetPred()) { - if (!loop.Has(*pred)) { - needNewExitBB = true; - break; - } + continue; + } + bool needNewExitBB = false; + for (auto pred : succ->GetPred()) { + if (!loop.Has(*pred)) { + needNewExitBB = true; + break; + } + } + if (needNewExitBB) { + // break the critical edge for code sinking + BB *newExitBB = cfg->NewBasicBlock(); + newExitBB->SetKind(kBBFallthru); + auto pos = succ->GetPredIndex(*curBB); + uint64_t freq = 0; + if (updateFreqs) { + int idx = curBB->GetSuccIndex(*succ); + ASSERT(idx >= 0 && idx < curBB->GetSuccFreq().size(), "sanity check"); + freq = curBB->GetSuccFreq()[static_cast(idx)]; + } + curBB->ReplaceSucc(succ, newExitBB); + succ->AddPred(*newExitBB, pos); + if (updateFreqs) { + newExitBB->SetFrequency(static_cast(freq)); + newExitBB->PushBackSuccFreq(freq); } - if (needNewExitBB) { - // break the critical edge for code sinking - BB *newExitBB = cfg->NewBasicBlock(); - newExitBB->SetKind(kBBFallthru); - auto pos = succ->GetPredIndex(*curBB); - uint64_t freq = 0; - if (updateFreqs) { - int idx = curBB->GetSuccIndex(*succ); - freq = curBB->GetSuccFreq()[idx]; - } - curBB->ReplaceSucc(succ, newExitBB); - succ->AddPred(*newExitBB, pos); - if (updateFreqs) { - newExitBB->SetFrequency(freq); - newExitBB->PushBackSuccFreq(freq); - } - if (!curBB->GetMeStmts().empty()) { - UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); - } - succ = newExitBB; - isCFGChange = true; + if (!curBB->GetMeStmts().empty()) { + UpdateTheOffsetOfStmtWhenTargetBBIsChange(*curBB, *succ, *newExitBB); } - loop.InsertInloopBB2exitBBs(*curBB, *succ); + succ = newExitBB; + isCFGChange = true; } + loop.InsertInloopBB2exitBBs(*curBB, *succ); } } } diff --git a/src/mapleall/maple_me/src/me_loop_inversion.cpp b/src/mapleall/maple_me/src/me_loop_inversion.cpp index d3f9505fed..4bef6afb01 100644 --- a/src/mapleall/maple_me/src/me_loop_inversion.cpp +++ b/src/mapleall/maple_me/src/me_loop_inversion.cpp @@ -204,7 +204,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMap exitbb is set 0 // latchBB fallthru is loop exit - int fallthrudiff = bb.GetSucc(0)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(0)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(0, bb.GetFrequency()); bb.SetSuccFreq(1, 0); @@ -219,7 +219,7 @@ void MeLoopInversion::Convert(MeFunction &func, BB &bb, BB &pred, MapleMapfallthru is loop exit, edge frequency of bb ->exitbb is set 0 // latchBB fallthru is in loop - int fallthrudiff = bb.GetSucc(1)->GetFrequency() - bb.GetFrequency(); + int fallthrudiff = static_cast(bb.GetSucc(1)->GetFrequency() - bb.GetFrequency()); if (fallthrudiff >= 0) { bb.SetSuccFreq(1, bb.GetFrequency()); bb.SetSuccFreq(0, 0); diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 0041c51b0d..6d510e4451 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -372,8 +372,8 @@ bool MEProfUse::PhaseRun(maple::MeFunction &f) { if (Options::profileUse) { result = profUse.MapleProfRun(); if (result) { - result = f.GetCfg()->VerifyBBFreq(); - if (result > 0 && (DEBUGFUNC_NEWPM(f))) { + result = f.GetCfg()->VerifyBBFreq() != 0 ? true : false; + if (result && (DEBUGFUNC_NEWPM(f))) { LogInfo::MapleLogger() << "func profileUse verification fail" << std::endl; } } diff --git a/src/mapleall/maple_me/src/me_value_range_prop.cpp b/src/mapleall/maple_me/src/me_value_range_prop.cpp index 1ac6ba7023..75279a690a 100644 --- a/src/mapleall/maple_me/src/me_value_range_prop.cpp +++ b/src/mapleall/maple_me/src/me_value_range_prop.cpp @@ -3142,14 +3142,14 @@ void ValueRangePropagation::AnalysisUnreachableBBOrEdge(BB &bb, BB &unreachableB int64_t removedFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { int idx = bb.GetSuccIndex(unreachableBB); - removedFreq = bb.GetSuccFreq()[idx]; + removedFreq = static_cast(bb.GetSuccFreq()[static_cast(idx)]); } bb.RemoveSucc(unreachableBB); bb.RemoveMeStmt(bb.GetLastMe()); bb.SetKind(kBBFallthru); if (func.GetCfg()->UpdateCFGFreq()) { bb.SetSuccFreq(0, bb.GetFrequency()); - succBB.SetFrequency(succBB.GetFrequency() + removedFreq); + succBB.SetFrequency(static_cast(succBB.GetFrequency() + removedFreq)); unreachableBB.SetFrequency(0); } auto *loop = loops->GetBBLoopParent(bb.GetBBId()); @@ -3524,9 +3524,9 @@ void ValueRangePropagation::RemoveUnreachableBB( condGotoBB.SetKind(kBBFallthru); // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - int64_t removedFreq = condGotoBB.GetSuccFreq()[1]; + int64_t removedFreq = static_cast(condGotoBB.GetSuccFreq()[1]); condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ0->SetFrequency(succ0->GetFrequency() + removedFreq); + succ0->SetFrequency(static_cast(succ0->GetFrequency() + removedFreq)); } condGotoBB.RemoveSucc(*succ1); DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ1, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); @@ -3543,12 +3543,12 @@ void ValueRangePropagation::RemoveUnreachableBB( int64_t removedFreq = 0; // update frequency before cfg changed if (func.GetCfg()->UpdateCFGFreq()) { - removedFreq = condGotoBB.GetSuccFreq()[0]; + removedFreq = static_cast(condGotoBB.GetSuccFreq()[0]); } condGotoBB.RemoveSucc(*succ0); if (func.GetCfg()->UpdateCFGFreq()) { condGotoBB.SetSuccFreq(0, condGotoBB.GetFrequency()); - succ1->SetFrequency(succ1->GetFrequency() + removedFreq); + succ1->SetFrequency(static_cast(succ1->GetFrequency() + removedFreq)); } DeleteThePhiNodeWhichOnlyHasOneOpnd(*succ0, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); condGotoBB.RemoveMeStmt(condGotoBB.GetLastMe()); @@ -3709,18 +3709,18 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - exitCopyFallthru->SetFrequency(exitCopyFallthru->GetFrequency() + edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + exitCopyFallthru->SetFrequency(static_cast(exitCopyFallthru->GetFrequency() + edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } return true; @@ -3758,17 +3758,17 @@ bool ValueRangePropagation::ChangeTheSuccOfPred2TrueBranch( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); } pred.RemoveSucc(bb); pred.AddSucc(*mergeAllFallthruBBs, index); if (func.GetCfg()->UpdateCFGFreq()) { - mergeAllFallthruBBs->SetFrequency(edgeFreq); - mergeAllFallthruBBs->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + mergeAllFallthruBBs->SetFrequency(static_cast(edgeFreq)); + mergeAllFallthruBBs->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); // update bb frequency ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); } mergeAllFallthruBBs->AddSucc(trueBranch); @@ -3831,13 +3831,18 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( BB &pred, BB &bb, BB &trueBranch, ScalarMeExpr *updateSSAExceptTheScalarExpr, std::map> &ssaupdateCandsForCondExpr) { CHECK_FATAL(bb.GetKind() == kBBCondGoto, "must be condgoto bb"); - if (GetRealPredSize(bb) >= kNumOperands) { + if (GetRealPredSize(bb) < kNumOperands) { + CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); + RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); + return true; + } + //if (GetRealPredSize(bb) >= kNumOperands) { if (OnlyHaveCondGotoStmt(bb)) { PrepareForSSAUpdateWhenPredBBIsRemoved(pred, bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3845,13 +3850,13 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(trueBranch, index); CreateLabelForTargetBB(pred, trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); // transform may not be consistent with frequency value updatedtrueFreq = updatedtrueFreq > 0 ? updatedtrueFreq : 0; - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } } else { auto *exitCopyFallthru = GetNewCopyFallthruBB(trueBranch, bb); @@ -3860,7 +3865,7 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); @@ -3868,14 +3873,14 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( pred.AddSucc(*exitCopyFallthru, index); CreateLabelForTargetBB(pred, *exitCopyFallthru); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); - exitCopyFallthru->SetFrequency(edgeFreq); - exitCopyFallthru->PushBackSuccFreq(edgeFreq); - size_t trueBranchIdx = bb.GetSuccIndex(trueBranch); - int64_t updatedtrueFreq = bb.GetSuccFreq()[trueBranchIdx] - edgeFreq; + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); + exitCopyFallthru->SetFrequency(static_cast(edgeFreq)); + exitCopyFallthru->PushBackSuccFreq(static_cast(edgeFreq)); + size_t trueBranchIdx = static_cast(bb.GetSuccIndex(trueBranch)); + int64_t updatedtrueFreq = static_cast(bb.GetSuccFreq()[static_cast(trueBranchIdx)] - edgeFreq); ASSERT(updatedtrueFreq >= 0, "sanity check"); - bb.SetSuccFreq(trueBranchIdx, updatedtrueFreq); - pred.AddSuccFreq(edgeFreq, index); + bb.SetSuccFreq(static_cast(trueBranchIdx), static_cast(updatedtrueFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } return true; } @@ -3892,27 +3897,27 @@ bool ValueRangePropagation::RemoveTheEdgeOfPredBB( size_t index = FindBBInSuccs(pred, bb); int64_t edgeFreq = 0; if (func.GetCfg()->UpdateCFGFreq()) { - edgeFreq = pred.GetSuccFreq()[index]; + edgeFreq = static_cast(pred.GetSuccFreq()[index]); ASSERT(bb.GetFrequency() >= edgeFreq, "sanity check"); } pred.RemoveSucc(bb); pred.AddSucc(*newBB, index); newBB->AddSucc(trueBranch); if (func.GetCfg()->UpdateCFGFreq()) { - bb.SetFrequency(bb.GetFrequency() - edgeFreq); + bb.SetFrequency(static_cast(bb.GetFrequency() - edgeFreq)); bb.UpdateEdgeFreqs(); - newBB->SetFrequency(edgeFreq); - newBB->PushBackSuccFreq(edgeFreq); - pred.AddSuccFreq(edgeFreq, index); + newBB->SetFrequency(static_cast(edgeFreq)); + newBB->PushBackSuccFreq(static_cast(edgeFreq)); + pred.AddSuccFreq(static_cast(edgeFreq), index); } DeleteThePhiNodeWhichOnlyHasOneOpnd(bb, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); (void)func.GetOrCreateBBLabel(trueBranch); CreateLabelForTargetBB(pred, *newBB); } - } else { - CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); - RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); - } +// } else { +// CHECK_FATAL(GetRealPredSize(bb) == 1, "must have one pred"); +// RemoveUnreachableBB(bb, trueBranch, updateSSAExceptTheScalarExpr, ssaupdateCandsForCondExpr); +// } return true; } diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index b6cc1f96bf..15d99ad5f6 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -712,8 +712,7 @@ class OptimizeBB { bool repeatOpt = false; // It will be always set false by OptBBIteratively. If there is some optimization // opportunity for currBB after a/some optimization, we should set it true. // Otherwise it will stop after all optimizations finished and continue to nextBB. - enum BBErrStat - { + enum BBErrStat { kBBNoErr, // BB is normal kBBErrNull, // BB is nullptr kBBErrOOB, // BB id is out-of-bound @@ -1763,13 +1762,13 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { int64_t deletedSuccFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = succ.GetSuccIndex(*rmBB); - deletedSuccFreq = succ.GetSuccFreq()[idx]; + deletedSuccFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); } succ.RemoveSucc(*rmBB, true); if (cfg->UpdateCFGFreq()) { succ.SetSuccFreq(0, succ.GetFrequency()); auto *succofSucc = succ.GetSucc(0); - succofSucc->SetFrequency(succofSucc->GetFrequency() + deletedSuccFreq); + succofSucc->SetFrequency(static_cast(succofSucc->GetFrequency() + deletedSuccFreq)); } DEBUG_LOG() << "Remove succ BB" << LOG_BBID(rmBB) << " of pred BB" << LOG_BBID(&succ) << "\n"; return true; @@ -1835,9 +1834,9 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { BB *affectedBB = (tfBranch == kBrTrue) ? stfSucc.first : stfSucc.second; idx = succ.GetSuccIndex(*affectedBB); ASSERT(idx >= 0 && idx < succ.GetSucc().size(), "sanity check"); - int64_t oldedgeFreq = succ.GetSuccFreq()[idx]; + int64_t oldedgeFreq = static_cast(succ.GetSuccFreq()[static_cast(idx)]); ASSERT(oldedgeFreq >= freq, "sanity check"); - succ.SetSuccFreq(idx, (oldedgeFreq - freq)); + succ.SetSuccFreq(idx, static_cast(oldedgeFreq - freq)); } return true; } @@ -2020,13 +2019,13 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { int64_t removedFreq = 0; if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*succ); - removedFreq = pred->GetSuccFreq()[idx]; + removedFreq = static_cast(pred->GetSuccFreq()[static_cast(idx)]); } if (pred->IsPredBB(*newTarget)) { pred->RemoveSucc(*succ, true); // one of pred's succ has been newTarget, avoid duplicate succ here if (cfg->UpdateCFGFreq()) { int idx = pred->GetSuccIndex(*newTarget); - pred->SetSuccFreq(idx, pred->GetSuccFreq()[idx] + removedFreq); + pred->SetSuccFreq(idx, static_cast(pred->GetSuccFreq()[static_cast(idx)] + removedFreq)); } } else { pred->ReplaceSucc(succ, newTarget); // phi opnd is not removed from currBB's philist, we will remove it later @@ -2035,7 +2034,7 @@ bool OptimizeBB::MergeGotoBBToPred(BB *succ, BB *pred) { if (cfg->UpdateCFGFreq()) { int64_t succFreq = succ->GetFrequency(); ASSERT(succFreq >= removedFreq, "sanity check"); - succ->SetFrequency(succFreq - removedFreq); + succ->SetFrequency(static_cast(succFreq - removedFreq)); succ->SetSuccFreq(0, succ->GetFrequency()); } DEBUG_LOG() << "Merge Uncond BB" << LOG_BBID(succ) << " to its pred BB" << LOG_BBID(pred) << ": BB" << LOG_BBID(pred) diff --git a/src/mapleall/maple_util/include/namemangler.h b/src/mapleall/maple_util/include/namemangler.h index c3333b16cf..fdc0f96022 100644 --- a/src/mapleall/maple_util/include/namemangler.h +++ b/src/mapleall/maple_util/include/namemangler.h @@ -213,7 +213,7 @@ uint32_t GetUnsignedLeb128Decode(const uint8_t **data); size_t GetUleb128Size(uint64_t val); size_t GetSleb128Size(int32_t val); bool NeedConvertUTF16(const std::string &str8); -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out); +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out); uint32_t EncodeULEB128(uint64_t value, std::ofstream &out); uint64_t DecodeULEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); int64_t DecodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr); diff --git a/src/mapleall/maple_util/src/mpl_profdata.cpp b/src/mapleall/maple_util/src/mpl_profdata.cpp index 849b262239..4c65c5496e 100644 --- a/src/mapleall/maple_util/src/mpl_profdata.cpp +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -13,7 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "mpl_profdata.h" - +#include #include "mpl_logging.h" #include "option.h" @@ -55,16 +55,18 @@ void MplProfileData::DumpProfileData() { } void ProfileSummary::ProcessHistogram() { - int countsum = 0; - int n = histogram.size(); - for (int i = n - 1; i >= 0; i--) { - countsum += histogram[i].countNums; - histogram[i].countRatio = ((float)(countsum) / (float)totalCount) * 100; + size_t countsum = 0; + size_t n = static_cast(histogram.size()); + enum PERCENTAGE {percent = 100}; + for (int32 i = n - 1; i >= 0; i--) { + countsum += histogram[static_cast(i)].countNums; + histogram[static_cast(i)].countRatio = std::round( + (static_cast(countsum) / static_cast(totalCount)) * percent); } } -#define HOTRATIO 90 uint64_t MplProfileData::GetHotThreshold() { + enum HOTNESS {HOTRATIO = 90}; for (auto &it : summary.GetHistogram()) { if (it.countRatio >= HOTRATIO) { hotCountThreshold = it.startValue; @@ -76,7 +78,8 @@ uint64_t MplProfileData::GetHotThreshold() { } } // should not be here - return 100; + const int unlikelyHot = 100; + return unlikelyHot; } bool MplProfileData::IsHotCallSite(uint64_t freq) { diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index c333420826..150b8c942d 100644 --- a/src/mapleall/maple_util/src/namemangler.cpp +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -597,7 +597,7 @@ size_t GetSleb128Size(int32_t v) { } // encode signed to output stream -uint32_t EncodeSLEB128(int64_t value, std::ofstream &out) { +uint32_t EncodeSLEB128(uint64_t value, std::ofstream &out) { bool more; uint32_t count = 0; do { @@ -631,64 +631,66 @@ uint32_t EncodeULEB128(uint64_t value, std::ofstream &out) { // decode a ULEB128 value. uint64_t DecodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; uint64_t value = 0; unsigned shift = 0; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } uint64_t slice = *p & 0x7f; - if ((shift >= 64 && slice != 0) || ((slice << shift) >> shift) != slice) { + if ((shift >= SIXTYFOUR && slice != ZERO) || ((slice << shift) >> shift) != slice) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } value += slice << shift; shift += kGreybackOffset; - } while (*p++ >= 128); + } while (*p++ >= ONEHUNDREDTWENTYEIGHT); if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } // decode a SLEB128 value. int64_t DecodeSLEB128(const uint8_t *p, unsigned *n, const uint8_t *end) { - const uint8_t *orig_p = p; + const uint8_t *origP = p; int64_t value = 0; unsigned shift = 0; uint8_t byte; + enum LITERALS {ONEHUNDREDTWENTYEIGHT = 128, SIXTYFOUR = 64, SIXTYTHREE = 63, ZERO = 0}; do { if (p == end) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } byte = *p; uint64_t slice = byte & 0x7f; - if ((shift >= 64 && slice != (value < 0 ? 0x7f : 0x00)) || - (shift == 63 && slice != 0 && slice != 0x7f)) { + if ((shift >= SIXTYFOUR && slice != (value < static_cast(ZERO) ? 0x7f : 0x00)) || + (shift == SIXTYTHREE && slice != ZERO && slice != 0x7f)) { if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } - return 0; + return ZERO; } - value |= slice << shift; + value |= static_cast(slice << shift); shift += kGreybackOffset; ++p; - } while (byte >= 128); + } while (byte >= ONEHUNDREDTWENTYEIGHT); // Sign extend negative numbers if needed. - if (shift < 64 && (byte & 0x40)) { - value |= (-1LL) << shift; + if (shift < SIXTYFOUR && (byte & 0x40)) { + value |= static_cast(0xffffffffffffffff) << shift; } if (n) { - *n = static_cast(p - orig_p); + *n = static_cast(p - origP); } return value; } diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index e0d6984461..f3850e2788 100644 --- a/src/mapleall/mpl2mpl/src/inline.cpp +++ b/src/mapleall/mpl2mpl/src/inline.cpp @@ -436,10 +436,10 @@ bool MInline::IsHotCallSite(const MIRFunction &caller, const MIRFunction &callee } // use maple instrument profile if (Options::profileUse) { - if (!caller.GetFuncProfData()) return false; - int64_t freq = caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID()); + if (!caller.GetFuncProfData()) {return false;} + int64_t freq = static_cast(caller.GetFuncProfData()->GetStmtFreq(callStmt.GetStmtID())); ASSERT(freq > 0, "sanity check"); - return module.GetMapleProfile()->IsHotCallSite((uint64_t)freq); + return module.GetMapleProfile()->IsHotCallSite(static_cast(freq)); } return module.GetProfile().CheckFuncHot(caller.GetName()); } diff --git a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp index 95bd0febdd..b8c73fa36d 100644 --- a/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -91,18 +91,18 @@ int FunctionProfileImport::ReadFuncProfile(MplProfileData *profData) { int MplProfDataParser::ReadMapleProfileData() { std::string mprofDataFile = Options::profile; if (mprofDataFile.empty()) { - if (const char *env_gcovprefix = std::getenv("GCOV_PREFIX")) { - mprofDataFile.append(env_gcovprefix); + if (const char *envGcovprefix = std::getenv("GCOV_PREFIX")) { + static_cast(mprofDataFile.append(envGcovprefix)); if (mprofDataFile.back() != '/') { - mprofDataFile.append("/"); + static_cast(mprofDataFile.append("/")); } if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix= " << mprofDataFile << std::endl; } uint32_t stripnum = 0; - if (const char *env_gcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { - std::string strip(env_gcovprefixstrip); - stripnum = std::stoi(strip); + if (const char *envGcovprefixstrip = std::getenv("GCOV_PREFIX_STRIP")) { + std::string strip(envGcovprefixstrip); + stripnum = static_cast(std::stoi(strip)); if (dumpDetail) { LogInfo::MapleLogger() << "set env gcov_prefix_strip=" << strip << std::endl; } @@ -124,7 +124,7 @@ int MplProfDataParser::ReadMapleProfileData() { LogInfo::MapleLogger() << "after strip, module profdata Name: " << profDataFileName << std::endl; } CHECK_FATAL(profDataFileName.size() > 0, "sanity check"); - mprofDataFile.append(profDataFileName); + static_cast(mprofDataFile.append(profDataFileName)); } else { // if gcov_prefix is not set, find .mprofdata according to m.profiledata mprofDataFile = m.GetProfileDataFileName(); @@ -133,7 +133,7 @@ int MplProfDataParser::ReadMapleProfileData() { } } // add .mprofdata - mprofDataFile.append(namemangler::kMplProfFileNameExt); + static_cast(mprofDataFile.append(namemangler::kMplProfFileNameExt)); } ASSERT(!mprofDataFile.empty(), "null check"); if (dumpDetail) { @@ -148,18 +148,18 @@ int MplProfDataParser::ReadMapleProfileData() { return 1; } // get length of file - inputStream.seekg(0, std::ios::end); - uint32_t length = inputStream.tellg(); - inputStream.seekg(0, std::ios::beg); + static_cast(inputStream.seekg(0, std::ios::end)); + uint32_t length = static_cast(inputStream.tellg()); + static_cast(inputStream.seekg(0, std::ios::beg)); const uint32_t sizeThreshold = 1024 * 10; CHECK_FATAL(length <= sizeThreshold, "NYI::large .mprofdata file size is larger than threashold, do chunk memory\n"); std::unique_ptr buffer = std::make_unique(length); - inputStream.read(buffer.get(), length); + static_cast(inputStream.read(buffer.get(), length)); inputStream.close(); // read 1st part summary ProfileSummaryImport summaryImport(mprofDataFile, inputStream); - summaryImport.SetPosition((uint8_t*)(buffer.get())); + summaryImport.SetPosition(reinterpret_cast(buffer.get())); int res = summaryImport.ReadSummary(profData); if (res) { LogInfo::MapleLogger() << "no summary part\n"; -- Gitee From 643f5e1c32aff42ead69cdf0793a9d76cfb3b611 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Mon, 15 Aug 2022 09:01:41 -0700 Subject: [PATCH 7/7] Fixed build errors introduced by last rebase --- src/mapleall/maple_me/src/optimizeCFG.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mapleall/maple_me/src/optimizeCFG.cpp b/src/mapleall/maple_me/src/optimizeCFG.cpp index 15d99ad5f6..2b4b073238 100644 --- a/src/mapleall/maple_me/src/optimizeCFG.cpp +++ b/src/mapleall/maple_me/src/optimizeCFG.cpp @@ -954,7 +954,7 @@ bool OptimizeBB::BranchBB2UncondBB(BB &bb) { EliminateEmptyConnectingBB(&bb, bb.GetSucc(static_cast(i)), destBB, *cfg); } while (bb.GetSucc().size() != 1) { // bb is an unconditional bb now, and its successor num should be 1 - ASSERT(bb.GetSucc().back() == destBB, "[FUNC: %s]Goto BB%d has different destination", funcName, LOG_BBID(&bb)); + ASSERT(bb.GetSucc().back() == destBB, "[FUNC: %s]Goto BB%d has different destination", funcName.c_str(), LOG_BBID(&bb)); bb.RemoveSucc(*bb.GetSucc().back()); } if (cfg->UpdateCFGFreq()) { @@ -1299,8 +1299,8 @@ bool OptimizeBB::IsProfitableForCond2Sel(MeExpr *condExpr, MeExpr *trueExpr, MeE if (trueExpr == falseExpr) { return true; } - ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName); - ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName); + ASSERT(IsSafeExpr(trueExpr), "[FUNC: %s]Please check for safety first", funcName.c_str()); + ASSERT(IsSafeExpr(falseExpr), "[FUNC: %s]Please check for safety first", funcName.c_str()); // try to simplify select expr MeExpr *selExpr = irmap->CreateMeExprSelect(trueExpr->GetPrimType(), *condExpr, *trueExpr, *falseExpr); MeExpr *simplifiedSel = irmap->SimplifyMeExpr(selExpr); @@ -1806,7 +1806,7 @@ bool OptimizeBB::SkipRedundantCond(BB &pred, BB &succ) { } BB *replacedSucc = isPredTrueBrSucc ? ptfSucc.first : ptfSucc.second; EliminateEmptyConnectingBB(&pred, replacedSucc, &succ, *cfg); - ASSERT(pred.IsPredBB(succ), "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName); + ASSERT(pred.IsPredBB(succ), "[FUNC: %s]After eliminate connecting BB, pred must be predecessor of succ", funcName.c_str()); int predPredIdx = succ.GetPredIndex(pred); // before replace succ, record predidx for UpdatePhiForMovingPred pred.ReplaceSucc(&succ, newBB, false); // do not update phi here, UpdatePhiForMovingPred will do it DEBUG_LOG() << "Replace succ BB" << LOG_BBID(replacedSucc) << " with BB" << LOG_BBID(newBB) << ": BB" @@ -2081,7 +2081,7 @@ bool OptimizeBB::OptimizeUncondBB() { } // wont exit BB and has an edge to commonExit, if we merge it to pred and delete it, the egde will be cut off if (currBB->GetSucc().size() == 2) { // 2 succ : first is gotoTarget, second is edge to commonExit - ASSERT(currBB->GetAttributes(kBBAttrWontExit), "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName, + ASSERT(currBB->GetAttributes(kBBAttrWontExit), "[FUNC: %s]GotoBB%d is not wontexitBB, but has two succ", funcName.c_str(), LOG_BBID(currBB)); return false; } -- Gitee