diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 63c33b5e583f0fdc54fb7ff98c83105470e37508..f88b63df39106d179650d18949599e709c54319a 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -28,6 +28,7 @@ #include "metadata_layout.h" #include "emit.h" #include "simplify.h" +#include namespace maplebe { using namespace maple; @@ -8948,6 +8949,49 @@ bool AArch64CGFunc::IsDuplicateAsmList(const MIRSymbol &sym) const { } void AArch64CGFunc::SelectMPLProfCounterInc(const IntrinsiccallNode &intrnNode) { + if (Options::profileGen) { + ASSERT(intrnNode.NumOpnds() == 1, "must be 1 operand"); + BaseNode *arg1 = intrnNode.Opnd(0); + ASSERT(arg1 != nullptr, "nullptr check"); + regno_t vRegNO1 = NewVReg(GetRegTyFromPrimTy(PTY_a64), GetPrimTypeSize(PTY_a64)); + RegOperand &vReg1 = CreateVirtualRegisterOperand(vRegNO1); + vReg1.SetRegNotBBLocal(); + static const MIRSymbol *bbProfileTab = nullptr; + + // Ref: MeProfGen::InstrumentFunc on ctrTbl naming + std::string ctrTblName = namemangler::kprefixProfCtrTbl + + GetMirModule().GetFileName() + "_" + GetName(); + std::replace(ctrTblName.begin(), ctrTblName.end(), '.', '_'); + std::replace(ctrTblName.begin(), ctrTblName.end(), '-', '_'); + std::replace(ctrTblName.begin(), ctrTblName.end(), '/', '_'); + + if (!bbProfileTab || bbProfileTab->GetName() != ctrTblName) { + bbProfileTab = GetMirModule().GetMIRBuilder()->GetGlobalDecl(ctrTblName); + CHECK_FATAL(bbProfileTab != nullptr, "expect counter table"); + } + + ConstvalNode *constvalNode = static_cast(arg1); + MIRConst *mirConst = constvalNode->GetConstVal(); + ASSERT(mirConst != nullptr, "nullptr check"); + CHECK_FATAL(mirConst->GetKind() == kConstInt, "expect MIRIntConst type"); + MIRIntConst *mirIntConst = safe_cast(mirConst); + int64 offset = GetPrimTypeSize(PTY_u64) * mirIntConst->GetValue(); + + if (!GetCG()->IsQuiet()) { + maple::LogInfo::MapleLogger(kLlInfo) << "At counter table offset: " << offset << std::endl; + } + MemOperand *memOpnd = &GetOrCreateMemOpnd(*bbProfileTab, offset, k64BitSize); + AArch64MemOperand &ctrMemOpnd = *static_cast(memOpnd); + if (IsImmediateOffsetOutOfRange(ctrMemOpnd, k64BitSize)) { + memOpnd = &SplitOffsetWithAddInstruction(ctrMemOpnd, k64BitSize); + } + Operand *reg = &SelectCopy(*memOpnd, PTY_u64, PTY_u64); + AArch64ImmOperand &one = CreateImmOperand(1, k64BitSize, false); + SelectAdd(*reg, *reg, one, PTY_u64); + SelectCopy(*memOpnd, PTY_u64, *reg, PTY_u64); + return; + } + ASSERT(intrnNode.NumOpnds() == 1, "must be 1 operand"); BaseNode *arg1 = intrnNode.Opnd(0); ASSERT(arg1 != nullptr, "nullptr check"); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_emitter.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_emitter.cpp index 26d79c03d84104a4c37eb86c6b9eba1dbd7750a0..ebcca62cb67b0bbb0db4b5221ac8361f13f682f5 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_emitter.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_emitter.cpp @@ -408,6 +408,14 @@ void AArch64AsmEmitter::Run(FuncEmitInfo &funcEmitInfo) { (void)emitter.Emit("\t.section\t.init_array,\"aw\"\n"); (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n"); } + if (cgFunc.GetFunction().GetAttr(FUNCATTR_initialization)) { + (void)emitter.Emit("\t.section\t.init_array,\"aw\"\n"); + (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n"); + } + if (cgFunc.GetFunction().GetAttr(FUNCATTR_termination)) { + (void)emitter.Emit("\t.section\t.fini_array,\"aw\"\n"); + (void)emitter.Emit("\t.quad\t").Emit(cgFunc.GetName()).Emit("\n"); + } emitter.Emit("\n"); EmitMethodDesc(funcEmitInfo, emitter); /* emit java code to the java section. */ diff --git a/src/mapleall/maple_be/src/cg/emit.cpp b/src/mapleall/maple_be/src/cg/emit.cpp index a7c2a137f3f6fdbcc003ce340f05e1f2955d6ca4..4df2c9ec5a928eebebcb3b6a2d71f58426d50673 100644 --- a/src/mapleall/maple_be/src/cg/emit.cpp +++ b/src/mapleall/maple_be/src/cg/emit.cpp @@ -1645,6 +1645,8 @@ void Emitter::EmitArrayConstant(MIRConst &mirConst) { } else if (elemConst->GetType().GetKind() == kTypeStruct || elemConst->GetType().GetKind() == kTypeClass || elemConst->GetType().GetKind() == kTypeUnion) { EmitStructConstant(*elemConst); + } else if (elemConst->GetKind() == kConstAddrofFunc) { + EmitScalarConstant(*elemConst); } else { ASSERT(false, "should not run here"); } diff --git a/src/mapleall/maple_driver/include/driver_option_common.h b/src/mapleall/maple_driver/include/driver_option_common.h index 0b79889d36684227fc6e5f33f092202e13e03e8a..8a583e16b9272366da5d20ae3aad5df948c30a4e 100644 --- a/src/mapleall/maple_driver/include/driver_option_common.h +++ b/src/mapleall/maple_driver/include/driver_option_common.h @@ -41,6 +41,8 @@ enum DriverOptionIndex { // DAI2.0 kDecoupleInit, kProfilePath, + kProfileGen, + kProfileUse, kGCOnly, kBigEndian, kMplcgOpt, diff --git a/src/mapleall/maple_driver/src/driver_option_common.cpp b/src/mapleall/maple_driver/src/driver_option_common.cpp index a59b93c8912376e6ba43b9baf8442cfef546901c..e84c980877d690360315061ba668226c2c50855d 100644 --- a/src/mapleall/maple_driver/src/driver_option_common.cpp +++ b/src/mapleall/maple_driver/src/driver_option_common.cpp @@ -221,6 +221,24 @@ const mapleOption::Descriptor kUsages[] = { " \t--profile=list_file\n", "driver", { "dex2mpl", "mpl2mpl", "mplcg" } }, + { kProfileGen, + kEnable, + "", + "profileGen", + kBuildTypeProduct, + kArgCheckPolicyBool, + " --profileGen \tGenerate profile data for static languages\n", + "driver", + { "me", "mpl2mpl", "mplcg" } }, + { kProfileUse, + kEnable, + "", + "profileUse", + kBuildTypeProduct, + kArgCheckPolicyBool, + " --profileUse \tOptimize static languages with profile data\n", + "driver", + { "me", "mpl2mpl", "mplcg" } }, { kGCOnly, kEnable, "", diff --git a/src/mapleall/maple_driver/src/mpl_options.cpp b/src/mapleall/maple_driver/src/mpl_options.cpp index 9bd86f1dcdb8a958d08e3af3f13d1518957ee0d0..4de0925df6bdaa9802fa1e8799227fe07bdbe1c5 100644 --- a/src/mapleall/maple_driver/src/mpl_options.cpp +++ b/src/mapleall/maple_driver/src/mpl_options.cpp @@ -152,7 +152,12 @@ ErrorCode MplOptions::HandleGeneralOptions() { LogInfo::MapleLogger() << kMapleDriverVersion << "\n"; return kErrorExitHelp; } - + case kProfileGen: { + exeOptions[kBinNameMe].push_back(opt); + exeOptions[kBinNameMpl2mpl].push_back(opt); + //exeOptions[kBinNameMplcg].push_back(opt); + continue; + } case kDex2mplOpt: updatedOptToolName = &kBinNameDex2mpl; break; diff --git a/src/mapleall/maple_ipa/include/ipa_phase_manager.h b/src/mapleall/maple_ipa/include/ipa_phase_manager.h index 39b95bc705aa72089b83387bd4413bd3cf0739b3..187737ed047a3aac97d5f05e3ca4022d8dc6e147 100644 --- a/src/mapleall/maple_ipa/include/ipa_phase_manager.h +++ b/src/mapleall/maple_ipa/include/ipa_phase_manager.h @@ -66,5 +66,19 @@ class SCCEmit : public MapleSccPhase>, public MaplePhaseManager private: void GetAnalysisDependence(maple::AnalysisDep &aDep) const override; }; + +class SCCProfile : public MapleSccPhase>, public MaplePhaseManager { + public: + explicit SCCProfile(MemPool *mp) : MapleSccPhase>(&id, mp), MaplePhaseManager(*mp) {} + ~SCCProfile() override = default; + std::string PhaseName() const override; + PHASECONSTRUCTOR(SCCProfile); + bool PhaseRun(SCCNode &f) override; + AnalysisDataManager *GetResult() { + return result; + } + private: + AnalysisDataManager *result = nullptr; +}; } // namespace maple #endif // MAPLE_IPA_INCLUDE_IPA_PHASE_MANAGER_H diff --git a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp index ddf7fd655178d93a66014a8e353960774e9be0a6..cede8ca0718b5edc3d6132a42f6371a7a0f6ea37 100644 --- a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp +++ b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp @@ -83,12 +83,16 @@ bool IpaSccPM::PhaseRun(MIRModule &m) { void IpaSccPM::DoPhasesPopulate(const MIRModule &mirModule) { (void)mirModule; - AddPhase("sccprepare", true); - AddPhase("prop_param_type", MeOption::npeCheckMode != SafetyCheckMode::kNoCheck); - AddPhase("prop_return_attr", MeOption::npeCheckMode != SafetyCheckMode::kNoCheck); - AddPhase("collect_ipa_info", true); - AddPhase("sccsideeffect", true); - AddPhase("sccemit", true); + if (Options::profileGen || Options::profileUse) { + AddPhase("sccprofile", true); + } else { + AddPhase("sccprepare", true); + AddPhase("prop_param_type", MeOption::npeCheckMode != SafetyCheckMode::kNoCheck); + AddPhase("prop_return_attr", MeOption::npeCheckMode != SafetyCheckMode::kNoCheck); + AddPhase("collect_ipa_info", true); + AddPhase("sccsideeffect", Options::sideEffect); + AddPhase("sccemit", true); + } } void IpaSccPM::GetAnalysisDependence(maple::AnalysisDep &aDep) const { @@ -183,7 +187,50 @@ void SCCEmit::GetAnalysisDependence(maple::AnalysisDep &aDep) const { aDep.AddRequired(); } +bool SCCProfile::PhaseRun(SCCNode &scc) { + SetQuiet(true); + AddPhase("mecfgbuild", true); + if (Options::profileGen) { + AddPhase("ssatab", true); + AddPhase("aliasclass", true); + AddPhase("ssa", true); + AddPhase("irmapbuild", true); + //AddPhase("profileIntrusionPM", true); //ref: MEProfGen + 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()); + for (auto *cgNode : scc.GetNodes()) { + MIRFunction *func = cgNode->GetMIRFunction(); + if (func->IsEmpty()) { + continue; + } + MIRModule &m = *func->GetModule(); + m.SetCurFunction(func); + MeFunction &meFunc = *func->GetMeFunc(); + 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); + } + } + } + return false; +} + MAPLE_ANALYSIS_PHASE_REGISTER(SCCPrepare, sccprepare) +MAPLE_ANALYSIS_PHASE_REGISTER(SCCProfile, sccprofile) MAPLE_ANALYSIS_PHASE_REGISTER(SCCCollectIpaInfo, collect_ipa_info); MAPLE_ANALYSIS_PHASE_REGISTER(SCCPropReturnAttr, prop_return_attr); MAPLE_TRANSFORM_PHASE_REGISTER(SCCPropParamType, prop_param_type); diff --git a/src/mapleall/maple_ir/include/all_attributes.def b/src/mapleall/maple_ir/include/all_attributes.def index 025166edbe03cbe30be3c2c944426cfba189c011..6f51deb7545f4fc236b457d2035005df21b72041 100644 --- a/src/mapleall/maple_ir/include/all_attributes.def +++ b/src/mapleall/maple_ir/include/all_attributes.def @@ -106,3 +106,7 @@ #if (defined(TYPE_ATTR) || defined(FIELD_ATTR)) && !defined(NOCONTENT_ATTR) ATTR(pack) #endif +#ifdef FUNC_ATTR + ATTR(initialization) + ATTR(termination) +#endif diff --git a/src/mapleall/maple_ir/include/mir_function.h b/src/mapleall/maple_ir/include/mir_function.h index 4767206ed60abe0c39abbc4cd1a656be276883ca..52ee2bccd10319133fc20f828a60b29f39e6e5a0 100644 --- a/src/mapleall/maple_ir/include/mir_function.h +++ b/src/mapleall/maple_ir/include/mir_function.h @@ -1113,6 +1113,42 @@ class MIRFunction { funcDesc = value; } + void SetProfCtrTbl(MIRSymbol *pct) { + CHECK_FATAL(Options::profileGen, "This is only for profileGen"); + profCtrTbl = pct; + } + + MIRSymbol *GetProfCtrTbl() { + return profCtrTbl; + } + + void SetNumCtrs(uint32 num) { + CHECK_FATAL(Options::profileGen, "This is only for profileGen"); + nCtrs = num; + } + + uint32 GetNumCtrs() { + return nCtrs; + } + + void SetFileLineNoChksum(uint64 chksum) { + CHECK_FATAL(Options::profileGen, "This is only for profileGen"); + fileLinenoChksum = chksum; + } + + uint64 GetFileLineNoChksum() { + return fileLinenoChksum; + } + + void SetCFGChksum(uint64 chksum) { + CHECK_FATAL(Options::profileGen, "This is only for profileGen"); + cfgChksum = chksum; + } + + uint64 GetCFGChksum() { + return cfgChksum; + } + void InitFuncDescToBest() { funcDesc.InitToBest(); } @@ -1234,7 +1270,10 @@ class MIRFunction { PointerAttr returnKind = PointerAttr::kPointerUndeiced; std::map paramNonullTypeMap; FuncDesc funcDesc{}; - + MIRSymbol *profCtrTbl = nullptr; + uint32 nCtrs = 0; // number of counters + uint64 fileLinenoChksum = 0; + uint64 cfgChksum = 0; void DumpFlavorLoweredThanMmpl() const; MIRFuncType *ReconstructFormals(const std::vector &symbols, bool clearOldArgs); }; diff --git a/src/mapleall/maple_ir/include/option.h b/src/mapleall/maple_ir/include/option.h index f3c2eb535cd63a669e6f627f81471af7b8d0ad6a..05abab257f72c41e51d7c316a6387ac46b4c49e6 100644 --- a/src/mapleall/maple_ir/include/option.h +++ b/src/mapleall/maple_ir/include/option.h @@ -147,6 +147,8 @@ class Options : public MapleDriverOptionBase { static std::string readDevirtualList; static bool usePreloadedClass; static std::string profile; + static bool profileGen; + static bool profileUse; static std::string appPackageName; static std::string proFileData; static std::string proFileFuncData; diff --git a/src/mapleall/maple_ir/src/option.cpp b/src/mapleall/maple_ir/src/option.cpp index 85f84739c0c5cec777168f0de6afec3c71b2a86d..fccdbc2922b4dae06cd6ef58b5f29b920fa5b46c 100644 --- a/src/mapleall/maple_ir/src/option.cpp +++ b/src/mapleall/maple_ir/src/option.cpp @@ -59,6 +59,9 @@ bool Options::emitVtableImpl = false; #if MIR_JAVA bool Options::skipVirtualMethod = false; #endif +bool Options::profileGen = false; +bool Options::profileUse = false; + // Ready to be deleted. bool Options::noRC = false; bool Options::analyzeCtor = true; @@ -1226,6 +1229,17 @@ bool Options::SolveOptions(const std::deque