diff --git a/src/mapleall/maple_ipa/BUILD.gn b/src/mapleall/maple_ipa/BUILD.gn index c4b868217296eab966a2245462109df3b70862d3..909eaf1bfc79440f921eaac4ba7fe4941fdaf555 100755 --- a/src/mapleall/maple_ipa/BUILD.gn +++ b/src/mapleall/maple_ipa/BUILD.gn @@ -36,6 +36,7 @@ src_libmplipa = [ "src/prop_parameter_type.cpp", "src/ipa_collect.cpp", "src/ipa_clone.cpp", + "src/ipa_gcovprofile.cpp", ] configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] diff --git a/src/mapleall/maple_ipa/include/ipa_gcovprofile.h b/src/mapleall/maple_ipa/include/ipa_gcovprofile.h new file mode 100644 index 0000000000000000000000000000000000000000..9ad1658f6b1fd5b3564b4d671a0a0d84cff8ba13 --- /dev/null +++ b/src/mapleall/maple_ipa/include/ipa_gcovprofile.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) [2021] Huawei Technologies Co.,Ltd.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_IPA_INCLUDE_IPA_GCOVPROFILE_H +#define MAPLE_IPA_INCLUDE_IPA_GCOVPROFILE_H +#include +#include +#include "mempool.h" +#include "mempool_allocator.h" +#include "mir_module.h" +#include "mir_function.h" +#include "me_phase_manager.h" +#include "gcov_parser.h" + +namespace maple { + +class IpaProfile : public MapleModulePhase, public MaplePhaseManager { + public: + explicit IpaProfile(MemPool *mp) : MapleModulePhase(&id, mp), MaplePhaseManager(*mp) {} + ~IpaProfile() override = default; + std::string PhaseName() const override; + PHASECONSTRUCTOR(IpaProfile); + bool PhaseRun(MIRModule &m) override; + AnalysisDataManager *GetResult() { + return result; + } + private: + void GetAnalysisDependence(maple::AnalysisDep &aDep) const override; + AnalysisDataManager *result = nullptr; +}; + +} // namespace maple +#endif // MAPLE_IPA_INCLUDE_IPA_GCOVPROFILE_H diff --git a/src/mapleall/maple_ipa/src/ipa_gcovprofile.cpp b/src/mapleall/maple_ipa/src/ipa_gcovprofile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bc4ac1a5fe3a68258f0948b293727151905b50a --- /dev/null +++ b/src/mapleall/maple_ipa/src/ipa_gcovprofile.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) [2021-2022] Huawei Technologies Co.,Ltd.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 "ipa_phase_manager.h" +#include "pme_emit.h" +#include "ipa_gcovprofile.h" + +namespace maple { + +void IpaProfile::GetAnalysisDependence(maple::AnalysisDep &aDep) const { + if (Options::profileUse) { + aDep.AddRequired(); + aDep.AddPreserved(); + } +} + +bool IpaProfile::PhaseRun(MIRModule &m) { + SetQuiet(true); + // keep original options value + bool oldProp = MeOption::propDuringBuild; + bool oldMerge = MeOption::mergeStmts; + uint8 oldOptLevel = MeOption::optLevel; + bool oldLayout = MeOption::layoutWithPredict; + MeOption::mergeStmts = false; + MeOption::propDuringBuild = false; + MeOption::layoutWithPredict = false; + MeOption::optLevel = 3; + + AddPhase("mecfgbuild", true); + if (Options::profileGen) { + AddPhase("ssatab", true); + AddPhase("aliasclass", true); + AddPhase("ssa", true); + AddPhase("irmapbuild", true); + AddPhase("profileGen", true); + } else { + AddPhase("profileUse", true); + } + AddPhase("emitforipa", true); + // Not like other phasemanager which use temp mempool to hold analysis results generated from the sub phases. + // Here we use GetManagerMemPool which lives longer than this phase(manager) itself to hold all the analysis result. + // So the following phase can access the result in this phase. + result = GetManagerMemPool()->New(*GetPhaseMemPool()); + auto iter = m.GetFunctionList().begin(); + for (; iter != m.GetFunctionList().end(); iter++) { + MIRFunction *func = *iter; + if (func == nullptr || func->GetFuncSymbol()->GetStorageClass() == kScUnused || + func->IsEmpty()) { + continue; + } + m.SetCurFunction(func); + auto meFuncMP = std::make_unique(memPoolCtrler, "ipa per-scc mempool"); + auto meFuncStackMP = std::make_unique(memPoolCtrler, ""); + MemPool *versMP = new ThreadLocalMemPool(memPoolCtrler, "first verst mempool"); + MeFunction &meFunc = *(meFuncMP->New(&m, func, meFuncMP.get(), *meFuncStackMP, versMP, "unknown")); + func->SetMeFunc(&meFunc); + meFunc.PartialInit(); + if (!IsQuiet()) { + LogInfo::MapleLogger() << "---Preparing Function for scc phase < " << func->GetName() << " > ---\n"; + } + meFunc.Prepare(); + + for (size_t i = 0; i < phasesSequence.size(); ++i) { + const MaplePhaseInfo *phase = MaplePhaseRegister::GetMaplePhaseRegister()->GetPhaseByID(phasesSequence[i]); + if (!IsQuiet()) { + LogInfo::MapleLogger() << " >> Prepare " << (phase->IsAnalysis() ? "analysis" : "transform") + << " Phase [ " << phase->PhaseName() << " ] <<\n"; + } + if (phase->IsAnalysis()) { + (void)RunAnalysisPhase(*phase, *result, meFunc, 1); + } else { + (void)RunTransformPhase(*phase, *result, meFunc, 1); + } + } + } + + // restore option value + MeOption::mergeStmts = oldMerge; + MeOption::propDuringBuild = oldProp; + MeOption::optLevel = oldOptLevel; + MeOption::layoutWithPredict = oldLayout; + return false; +} +} // namespace maple diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 4767206ed60abe0c39abbc4cd1a656be276883ca..d01ff932706b19036aee76e890caa9332eaa7224 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1139,6 +1139,8 @@ class MIRFunction { void SetIsVisited() { isVisited = true; } + // compute function ident value + unsigned ComputeFuncIdent(); private: MIRModule *module; // the module that owns this function PUIdx puIdx = 0; // the PU index of this function diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index 4421bfc2b027dc00b7cf543cee9e6c9c585631c2..aef9f3ea80bb30ba614ae25b12e6675b03f7c8e9 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -21,6 +21,7 @@ #include "mpl_logging.h" #include "muid.h" #include "profile.h" +#include "gcov_profile.h" #if MIR_FEATURE_FULL #include #include @@ -253,6 +254,13 @@ class MIRModule { return profile; } + GcovProfileData* GetGcovProfile() { + return gcovProfile; + } + void SetGcovProfile(GcovProfileData* info) { + gcovProfile = info; + } + void SetSomeSymbolNeedForDecl(bool s) { someSymbolNeedForwDecl = s; } @@ -682,6 +690,7 @@ class MIRModule { MapleSet symbolSet; MapleVector symbolDefOrder; Profile profile; + GcovProfileData* gcovProfile; bool someSymbolNeedForwDecl = false; // some symbols' addressses used in initialization std::ostream &out; diff --git a/src/mapleall/maple_ir/include/option.h b/src/mapleall/maple_ir/include/option.h index f3c2eb535cd63a669e6f627f81471af7b8d0ad6a..efdd1f982aa91328590ea9ee579dcb07521f90e0 100644 --- a/src/mapleall/maple_ir/include/option.h +++ b/src/mapleall/maple_ir/include/option.h @@ -112,6 +112,10 @@ class Options : public MapleDriverOptionBase { #if MIR_JAVA static bool skipVirtualMethod; #endif + static bool profileGen; + static bool profileUse; + static std::string profGenDataFile; + static std::string profUseDataFile; // Ready to be deleted. static bool noRC; static bool analyzeCtor; diff --git a/src/mapleall/maple_ir/src/mir_function.cpp b/src/mapleall/maple_ir/src/mir_function.cpp index e9e85f459905b12878c4c381d65641487d04a2d8..8a8db5cf47b1a5b6a36898cf6ad13c93c6e23e14 100644 --- a/src/mapleall/maple_ir/src/mir_function.cpp +++ b/src/mapleall/maple_ir/src/mir_function.cpp @@ -36,6 +36,8 @@ enum FuncProp : uint32_t { } // namespace namespace maple { +extern unsigned coverage_checksum_string (unsigned chksum, const char *string); + const MIRSymbol *MIRFunction::GetFuncSymbol() const { return GlobalTables::GetGsymTable().GetSymbolFromStidx(symbolTableIdx.Idx()); } @@ -663,6 +665,21 @@ void MIRFunction::NewBody() { } } +// used in gcov profile +unsigned MIRFunction::ComputeFuncIdent() { + unsigned chksum = 0; + const std::string& func_name = GetName(); + if (IsExtern() || !IsStatic()) { + chksum = coverage_checksum_string(0, func_name.c_str()); + } else { + ASSERT(0, "unhandled local method"); + } + /* Non-negative integers are hopefully small enough to fit in all targets. + Gcov file formats wants non-zero function IDs. */ + chksum = chksum & 0x7fffffff; + return chksum + (!chksum); +} + #ifdef DEBUGME void MIRFunction::SetUpGDBEnv() { if (codeMemPool != nullptr) { diff --git a/src/mapleall/maple_ir/src/option.cpp b/src/mapleall/maple_ir/src/option.cpp index 85f84739c0c5cec777168f0de6afec3c71b2a86d..53bab3e0137f38e58566e917c3c1307bc31764d2 100644 --- a/src/mapleall/maple_ir/src/option.cpp +++ b/src/mapleall/maple_ir/src/option.cpp @@ -59,6 +59,10 @@ bool Options::emitVtableImpl = false; #if MIR_JAVA bool Options::skipVirtualMethod = false; #endif +bool Options::profileGen = false; +std::string Options::profGenDataFile = ""; +bool Options::profileUse = false; +std::string Options::profUseDataFile = ""; // Ready to be deleted. bool Options::noRC = false; bool Options::analyzeCtor = true; @@ -147,6 +151,8 @@ enum OptionIndex { kProfileColdCount, kProfileHotRate, kProfileColdRate, + kProfileGen, + kProfileUse, // Ready to be deleted. kMpl2MplUseRc, kMpl2MplStrictNaiveRc, @@ -422,6 +428,24 @@ const Descriptor kUsage[] = { " --profile-cold-rate=900000 \tA count is regarded as cold if it is in the smallest 10%\n", "mpl2mpl", {} }, + { kProfileGen, + kEnable, + "", + "profile-gen", + kBuildTypeExperimental, + kArgCheckPolicyOptional, + " --profile-gen \tGenerate profile data\n", + "mpl2mpl", + {} }, + { kProfileUse, + kEnable, + "", + "profile-use", + kBuildTypeExperimental, + kArgCheckPolicyOptional, + " --profile-use \tRead profile data\n", + "mpl2mpl", + {} }, { kNativeWrapper, kEnable, "", @@ -1108,6 +1132,14 @@ bool Options::SolveOptions(const std::deque