From c5b1d35ab15aac9fb5f779946f9a975899380220 Mon Sep 17 00:00:00 2001 From: linma Date: Thu, 21 Jul 2022 13:19:17 -0700 Subject: [PATCH] pgo: rewrite profile data parser to accept maple profile data format --- 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 | 13 +- .../maple_me/include/me_profile_use.h | 5 +- src/mapleall/maple_me/include/pme_emit.h | 2 +- src/mapleall/maple_me/src/me_cfg.cpp | 4 +- src/mapleall/maple_me/src/me_profile_use.cpp | 26 +- src/mapleall/maple_util/BUILD.gn | 1 + .../{gcov_profile.h => mpl_profdata.h} | 115 ++++-- src/mapleall/maple_util/include/namemangler.h | 5 + src/mapleall/maple_util/src/mpl_profdata.cpp | 53 +++ src/mapleall/maple_util/src/namemangler.cpp | 92 +++++ src/mapleall/mpl2mpl/BUILD.gn | 2 +- src/mapleall/mpl2mpl/include/gcov_parser.h | 117 ------ .../mpl2mpl/include/inline_transformer.h | 6 +- .../mpl2mpl/include/mpl_profdata_parser.h | 111 ++++++ src/mapleall/mpl2mpl/src/call_graph.cpp | 4 +- src/mapleall/mpl2mpl/src/gcov_parser.cpp | 359 ------------------ src/mapleall/mpl2mpl/src/gen_profile.cpp | 2 +- src/mapleall/mpl2mpl/src/inline.cpp | 4 +- .../mpl2mpl/src/inline_transformer.cpp | 17 +- .../mpl2mpl/src/module_phase_manager.cpp | 4 +- .../mpl2mpl/src/mpl_profdata_parser.cpp | 162 ++++++++ 25 files changed, 567 insertions(+), 557 deletions(-) rename src/mapleall/maple_util/include/{gcov_profile.h => mpl_profdata.h} (37%) 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 9c29ae1943..8ea7a1d12d 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 e2271b3f5f..d473d76cb5 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 f6122d2ee4..51073f76f9 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1258,13 +1258,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) { @@ -1371,7 +1371,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..be748df3f5 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) { @@ -345,7 +345,6 @@ class MIRModule { std::replace(profileDataFileName.begin(), profileDataFileName.end(), '.', '_'); std::replace(profileDataFileName.begin(), profileDataFileName.end(), '-', '_'); std::replace(profileDataFileName.begin(), profileDataFileName.end(), '/', '_'); - profileDataFileName = profileDataFileName + namemangler::kProfFileNameExt; return profileDataFileName; } @@ -710,7 +709,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_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 1a192138e6..19424dd4d1 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/me_cfg.cpp b/src/mapleall/maple_me/src/me_cfg.cpp index c1f650b7bb..2e7ccf46a9 100644 --- a/src/mapleall/maple_me/src/me_cfg.cpp +++ b/src/mapleall/maple_me/src/me_cfg.cpp @@ -1868,7 +1868,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; } @@ -1908,7 +1908,7 @@ void MeCFG::ConstructBBFreqFromStmtFreq() { } void MeCFG::ConstructStmtFreq() { - GcovFuncInfo* funcData = func.GetMirFunc()->GetFuncProfData(); + FuncProfInfo* funcData = func.GetMirFunc()->GetFuncProfData(); if (!funcData) { return; } diff --git a/src/mapleall/maple_me/src/me_profile_use.cpp b/src/mapleall/maple_me/src/me_profile_use.cpp index 0a4d1ea0f7..4d9c62b6ad 100644 --- a/src/mapleall/maple_me/src/me_profile_use.cpp +++ b/src/mapleall/maple_me/src/me_profile_use.cpp @@ -294,12 +294,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 +315,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")) { + 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,10 +336,10 @@ 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'; + << funcData->edgeCounts << " func real counter " << instrumentBBs.size() << '\n'; } func->GetMirFunc()->SetFuncProfData(nullptr); // clear func profile data return false; @@ -368,8 +368,10 @@ 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) { + f.GetCfg()->VerifyBBFreq(); + } } else { profUse.Run(); } 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/mpl_profdata.h similarity index 37% rename from src/mapleall/maple_util/include/gcov_profile.h rename to src/mapleall/maple_util/include/mpl_profdata.h index baf50aa973..6aa8c1520f 100644 --- a/src/mapleall/maple_util/include/gcov_profile.h +++ b/src/mapleall/maple_util/include/mpl_profdata.h @@ -1,32 +1,26 @@ /* - * Copyright (c) [2022] Futurewei Technologies Co., Ltd. All rights reserved. + * Copyright (c) [2022] Futurewei Technologies, Inc. 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: + * 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: * - * https://opensource.org/licenses/MulanPSL-2.0 + * 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 MulanPSL - 2.0 for more details. + * See the Mulan PSL v2 for more details. */ -#ifndef MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H -#define MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H - +#ifndef MAPLE_UTIL_INCLUDE_MPL_PROFDATA_H +#define MAPLE_UTIL_INCLUDE_MPL_PROFDATA_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, @@ -35,11 +29,60 @@ enum UpdateFreqOp { kUpdateUnrollRemainderFreq = 0x8, }; -class GcovFuncInfo { +// used for record cumulative datas +struct ProfileSummaryHistogram { + 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) : + startValue(s), countNums(num), countMinVal(mincount), countCumValue(cumcounts) { + } +}; + +class ProfileSummary { +public: + 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(); } + 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: - 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; + FuncProfInfo(MapleAllocator* alloc, unsigned funcIdent, unsigned lineno_cs, + unsigned cfg_cs, unsigned countnum = 0) : ident(funcIdent), linenoChecksum(lineno_cs), + cfgChecksum(cfg_cs), edgeCounts(countnum), counts(alloc->Adapter()) {}; + ~FuncProfInfo() = default; uint64_t GetFuncFrequency() const { return entry_freq; } void SetFuncFrequency(uint64_t freq) { entry_freq = freq; } @@ -77,34 +120,48 @@ class GcovFuncInfo { ASSERT(0, "should not be here"); return false; } + void DumpFunctionProfile(); + unsigned ident; - unsigned lineno_checksum; - unsigned cfg_checksum; + unsigned linenoChecksum; + unsigned cfgChecksum; // Raw arc coverage counts. - unsigned num_counts; - MapleVector counts; + unsigned edgeCounts; + 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 { +class MplProfileData { public: - GcovProfileData(MapleAllocator *alloc) : funcsCounter(alloc->Adapter()) {} + MplProfileData(MemPool *m, MapleAllocator *a) : funcsCounter(a->Adapter()), summary(a), mp(m), alloc(a) {} - GcovFuncInfo *GetFuncProfile(unsigned puidx) { + FuncProfInfo *GetFuncProfile(unsigned puidx) { if (funcsCounter.count(puidx) > 0) { return funcsCounter[puidx]; } return nullptr; } - void AddFuncProfile(unsigned puidx, GcovFuncInfo *funcData) { + FuncProfInfo *AddNewFuncProfile(unsigned puidx, unsigned lino_cs, unsigned cfg_cs, unsigned countnum) { + FuncProfInfo *funcProf = mp->New(alloc, puidx, lino_cs, cfg_cs, 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; } - MapleUnorderedMap funcsCounter; // use puidx as key + void DumpProfileData(); + void DumpFunctionsProfile(); + MapleUnorderedMap funcsCounter; // use puidx as key + // record module profile information and statistics of count information + ProfileSummary summary; +private: + MemPool *mp; + MapleAllocator *alloc; }; - } // end namespace -#endif // MAPLE_UTIL_INCLUDE_GCOV_PROFILE_H +#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..c1b21573fe 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..64e37ed9c0 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_profdata.cpp @@ -0,0 +1,53 @@ +/* + * 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" +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 (int 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(); +} +} // endof namespace diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp index b2dbd0ca91..151a97f371 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 @@ -593,4 +594,95 @@ size_t GetSleb128Size(int32_t v) { } 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 >>= 7; + 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 << (char)(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 >>= 7; + 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 = (unsigned)(p - orig_p); + return 0; + } + uint64_t Slice = *p & 0x7f; + if ((Shift >= 64 && Slice != 0) || Slice << Shift >> Shift != Slice) { + if (n) + *n = (unsigned)(p - orig_p); + return 0; + } + Value += Slice << Shift; + Shift += 7; + } while (*p++ >= 128); + if (n) + *n = (unsigned)(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 = (unsigned)(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 = (unsigned)(p - orig_p); + return 0; + } + Value |= Slice << Shift; + Shift += 7; + ++p; + } while (Byte >= 128); + // Sign extend negative numbers if needed. + if (Shift < 64 && (Byte & 0x40)) + Value |= (-1ULL) << Shift; + if (n) + *n = (unsigned)(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..1569f9b900 100644 --- a/src/mapleall/mpl2mpl/include/inline_transformer.h +++ b/src/mapleall/mpl2mpl/include/inline_transformer.h @@ -55,7 +55,10 @@ 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 +94,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..95513fd835 --- /dev/null +++ b/src/mapleall/mpl2mpl/include/mpl_profdata_parser.h @@ -0,0 +1,111 @@ +/* + * 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 "mempool.h" +#include "mempool_allocator.h" +#include "bb.h" +#include "maple_phase_manager.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) { + } + virtual ~MplProfDataParser() { + } + 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 07d356a3c5..a65422a56a 100644 --- a/src/mapleall/mpl2mpl/src/call_graph.cpp +++ b/src/mapleall/mpl2mpl/src/call_graph.cpp @@ -190,7 +190,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,7 +199,7 @@ 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(); } 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 b40806896a..ae32d2bed1 100644 --- a/src/mapleall/mpl2mpl/src/gen_profile.cpp +++ b/src/mapleall/mpl2mpl/src/gen_profile.cpp @@ -104,7 +104,7 @@ 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))); modProfDescSymMirConst->AddItem(profileFNMirConst, 6); diff --git a/src/mapleall/mpl2mpl/src/inline.cpp b/src/mapleall/mpl2mpl/src/inline.cpp index 4b1c4ca460..4b7543ee76 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; } @@ -421,7 +421,7 @@ 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()); } diff --git a/src/mapleall/mpl2mpl/src/inline_transformer.cpp b/src/mapleall/mpl2mpl/src/inline_transformer.cpp index 87d79fab1a..030b077931 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); @@ -560,7 +559,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()); } } @@ -604,7 +603,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()); } } @@ -621,7 +620,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 @@ -637,7 +636,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"); @@ -661,7 +660,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..de5c758b74 --- /dev/null +++ b/src/mapleall/mpl2mpl/src/mpl_profdata_parser.cpp @@ -0,0 +1,162 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "option.h" +#include "mpl_logging.h" +#include "mpl_profdata_parser.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 (int 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 (int 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 (int 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_p = std::getenv("GCOV_PREFIX")) { + mprofDataFile.append(env_p); + } else { + mprofDataFile.append("."); + } + mprofDataFile.append("/"); + mprofDataFile.append(m.GetProfileDataFileName()); + mprofDataFile.append(namemangler::kMplProfFileNameExt); + } + ASSERT(!mprofDataFile.empty(), "null check"); + + // 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, inputStream.end); + int length = inputStream.tellg(); + inputStream.seekg (0, inputStream.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(new char[sizeof(char) * 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 + MplProfDataParser parser(m, memPool, true/*debug*/); + 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