From 177331dd63354123eedae82ab850b7093353a48c Mon Sep 17 00:00:00 2001 From: fye Date: Sat, 19 Nov 2022 13:05:51 -0800 Subject: [PATCH 1/2] PGO: bring profile onto cg --- src/mapleall/maple_be/BUILD.gn | 1 + .../include/cg/aarch64/aarch64_phases.def | 1 + .../maple_be/include/cg/cg_profile_use.h | 180 ++++++++++++++++++ src/mapleall/maple_be/include/cg/cgbb.h | 44 ++++- .../maple_be/src/cg/cg_profile_use.cpp | 86 +++++++++ .../maple_be/src/cg/optimize_common.cpp | 28 ++- .../maple_ipa/src/ipa_phase_manager.cpp | 4 +- 7 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 src/mapleall/maple_be/include/cg/cg_profile_use.h create mode 100644 src/mapleall/maple_be/src/cg/cg_profile_use.cpp diff --git a/src/mapleall/maple_be/BUILD.gn b/src/mapleall/maple_be/BUILD.gn index ed4d66787e..c9ab7ea199 100644 --- a/src/mapleall/maple_be/BUILD.gn +++ b/src/mapleall/maple_be/BUILD.gn @@ -226,6 +226,7 @@ src_libcgphases = [ "src/cg/cg_ssa_pre.cpp", "src/cg/cg_pgo_gen.cpp", "src/cg/cg_pgo_use.cpp", + "src/cg/cg_profile_use.cpp", "src/cg/regsaves.cpp", "src/cg/cg_critical_edge.cpp", "src/cg/alignment.cpp", diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def b/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def index 48e835dbb3..03da2fb86b 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_phases.def @@ -16,6 +16,7 @@ ADDTARGETPHASE("createstartendlabel", true); ADDTARGETPHASE("buildehfunc", !GetMIRModule()->IsCModule()); ADDTARGETPHASE("handlefunction", true); + ADDTARGETPHASE("cgprofuse", Options::profileUse); ADDTARGETPHASE("moveargs", true); /* SSA PHASES */ ADDTARGETPHASE("cgssaconstruct", CGOptions::DoCGSSA()); diff --git a/src/mapleall/maple_be/include/cg/cg_profile_use.h b/src/mapleall/maple_be/include/cg/cg_profile_use.h new file mode 100644 index 0000000000..642f9a958f --- /dev/null +++ b/src/mapleall/maple_be/include/cg/cg_profile_use.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reverved. + * + * 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 MAPLEBE_INCLUDE_CG_PROFUSE_H +#define MAPLEBE_INCLUDE_CG_PROFUSE_H + +#include "cgfunc.h" + +namespace maplebe { +class CgProfUse { + public: + + struct Edge { + BB *src; + BB *dst; + Edge *next = nullptr; // the edge with the same src + uint64 frequency = 0; // later uint64_t + bool status = false; // True value indicates the edge's freq is determined + Edge(BB *bb1, BB *bb2) : src(bb1), dst(bb2) {} + }; + + CgProfUse(CGFunc &f, MemPool &mp) + : cgFunc(&f), memPool(&mp), alloc(&mp), allEdges(alloc.Adapter()), + BB2InEdges(alloc.Adapter()), BB2OutEdges(alloc.Adapter()) {} + + virtual ~CgProfUse() = default; + + void setupProf(); + + MapleSet &GetAllEdges() { + return allEdges; + } + + Edge *CreateEdge(BB *src, BB *dst) { + Edge *e = memPool->New(src, dst); + allEdges.insert(e); + return e; + } + + void SetupBB2Edges() { + for (Edge *e : allEdges) { + auto it = BB2InEdges.find(e->dst); + if (it == BB2InEdges.end()) { + MapleVector edgeVec(alloc.Adapter()); + edgeVec.push_back(e); + BB2InEdges.emplace(e->dst, edgeVec); + } else { + MapleVector &edgeVec = it->second; + edgeVec.push_back(e); + } + + it = BB2OutEdges.find(e->src); + if (it == BB2OutEdges.end()) { + MapleVector edgeVec(alloc.Adapter()); + edgeVec.push_back(e); + BB2OutEdges.emplace(e->src, edgeVec); + } else { + MapleVector &edgeVec = it->second; + edgeVec.push_back(e); + } + } + } + + void SetSuccsFreq() { + for (Edge *e : allEdges) { + e->src->SetEdgeProfFreq(e->dst, e->frequency); + } + } + + void InferEdgeFreq() { + std::queue bbQueue; + FOR_ALL_BB(bb, cgFunc) { + bbQueue.push(bb); + } + + while (!bbQueue.empty()) { + BB *bb = bbQueue.front(); + bbQueue.pop(); + + // Type 1 inference + uint32 knownEdges1 = 0; + uint64 freqSum1 = 0; + Edge * unknownEdge1 = nullptr; + MapleMap>::iterator iit = BB2InEdges.find(bb); + if ((iit != BB2InEdges.end()) && (iit->second.size() != 0)) { + for (Edge *e : iit->second ) { + if (e->status) { + knownEdges1++; + freqSum1 += e->frequency; + } else { + unknownEdge1 = e; + } + } + if ((knownEdges1 == iit->second.size() - 1) && (bb->GetProfFreq() != 0)) { + if (bb->GetProfFreq() >= freqSum1) { + unknownEdge1->status = true; + unknownEdge1->frequency = bb->GetProfFreq() - freqSum1; + bbQueue.push(unknownEdge1->src); + bbQueue.push(unknownEdge1->dst); + } + } + } + + // Type 2 inference + uint32 knownEdges2 = 0; + uint64 freqSum2 = 0; + Edge * unknownEdge2 = nullptr; + MapleMap>::iterator oit = BB2OutEdges.find(bb); + if ((oit != BB2OutEdges.end()) && (oit->second.size() != 0)) { + for (Edge *e : oit->second ) { + if (e->status) { + knownEdges2++; + freqSum2 += e->frequency; + } else { + unknownEdge2 = e; + } + } + if ((knownEdges2 == oit->second.size() - 1) && (bb->GetProfFreq() != 0)) { + if (bb->GetProfFreq() >= freqSum2) { + unknownEdge2->status = true; + unknownEdge2->frequency = bb->GetProfFreq() - freqSum2; + bbQueue.push(unknownEdge2->src); + bbQueue.push(unknownEdge2->dst); + } + } + } + + // Type 3 inference + if ((unknownEdge1 != nullptr) && (unknownEdge1->status == false) && + (iit != BB2InEdges.end()) && (iit->second.size() != 0) && + (knownEdges1 == iit->second.size() - 1) && + (knownEdges2 > 0) && (unknownEdge2 == nullptr)) { + if (freqSum2 >= freqSum1) { + unknownEdge1->status = true; + unknownEdge1->frequency = freqSum2 - freqSum1; + bbQueue.push(unknownEdge1->src); + bbQueue.push(unknownEdge1->dst); + } + } + + if ((unknownEdge2 != nullptr) && (unknownEdge2->status == false) && + (oit != BB2InEdges.end()) && (oit->second.size() != 0) && + (knownEdges2 == oit->second.size() - 1) && + (knownEdges1 > 0) && (unknownEdge1 == nullptr)) { + if (freqSum1 >= freqSum2) { + unknownEdge2->status = true; + unknownEdge2->frequency = freqSum1 - freqSum2; + bbQueue.push(unknownEdge2->src); + bbQueue.push(unknownEdge2->dst); + } + } + + } + } + + protected: + CGFunc *cgFunc; + MemPool *memPool; + MapleAllocator alloc; + MapleSet allEdges; + MapleMap> BB2InEdges; + MapleMap> BB2OutEdges; + private: +}; + +MAPLE_FUNC_PHASE_DECLARE(CGProfUse, maplebe::CGFunc) +} +#endif /* MAPLEBE_INCLUDE_CG_PROFUSE_H */ diff --git a/src/mapleall/maple_be/include/cg/cgbb.h b/src/mapleall/maple_be/include/cg/cgbb.h index 91ac332c64..38476f804e 100644 --- a/src/mapleall/maple_be/include/cg/cgbb.h +++ b/src/mapleall/maple_be/include/cg/cgbb.h @@ -102,6 +102,7 @@ class BB { loopPreds(mallocator.Adapter()), loopSuccs(mallocator.Adapter()), succsFreq(mallocator.Adapter()), + succsProfFreq(mallocator.Adapter()), liveInRegNO(mallocator.Adapter()), liveOutRegNO(mallocator.Adapter()), callInsns(mallocator.Adapter()), @@ -281,6 +282,12 @@ class BB { void SetFrequency(uint32 arg) { frequency = arg; } + uint64 GetProfFreq() const { + return profFreq; + } + void SetProfFreq(uint64 arg) { + profFreq = arg; + } BB *GetNext() { return next; } @@ -804,11 +811,45 @@ class BB { succsFreq[idx] = freq; } + void InitEdgeProfFreq() { + succsProfFreq.resize(succs.size(), 0); + } + + uint64 GetEdgeProfFreq(const BB &bb) const { + auto iter = std::find(succs.begin(), succs.end(), &bb); + if (iter == std::end(succs) || succs.size() > succsProfFreq.size()) { + return 0; + } + CHECK_FATAL(iter != std::end(succs), "%d is not the successor of %d", bb.GetId(), this->GetId()); + CHECK_FATAL(succs.size() == succsProfFreq.size(), "succProfFreq size doesn't match succ size"); + const size_t idx = static_cast(std::distance(succs.begin(), iter)); + return succsProfFreq[idx]; + } + + uint64 GetEdgeProfFreq(size_t idx) const { + if (idx >= succsProfFreq.size()) { + return 0; + } + CHECK_FATAL(idx < succsProfFreq.size(), "out of range in BB::GetEdgeProfFreq"); + CHECK_FATAL(succs.size() == succsProfFreq.size(), "succProfFreq size doesn't match succ size"); + return succsProfFreq[idx]; + } + + void SetEdgeProfFreq(BB *bb, uint64 freq) { + auto iter = std::find(succs.begin(), succs.end(), bb); + CHECK_FATAL(iter != std::end(succs), "%d is not the successor of %d", bb->GetId(), this->GetId()); + CHECK_FATAL(succs.size() == succsProfFreq.size(), + "succProfFreq size %d doesn't match succ size %d", succsProfFreq.size(), succs.size()); + const size_t idx = static_cast(std::distance(succs.begin(), iter)); + succsProfFreq[idx] = freq; + } + private: static const std::string bbNames[kBBLast]; uint32 id; uint32 level = 0; uint32 frequency = 0; + uint64 profFreq = 0; // profileUse BB *prev = nullptr; /* Doubly linked list of BBs; */ BB *next = nullptr; /* They represent the order in which blocks are to be emitted. */ @@ -825,9 +866,8 @@ class BB { MapleList ehSuccs; MapleList loopPreds; MapleList loopSuccs; - MapleVector succsFreq; - + MapleVector succsProfFreq; /* this is for live in out analysis */ MapleSet liveInRegNO; MapleSet liveOutRegNO; diff --git a/src/mapleall/maple_be/src/cg/cg_profile_use.cpp b/src/mapleall/maple_be/src/cg/cg_profile_use.cpp new file mode 100644 index 0000000000..45bb9f075d --- /dev/null +++ b/src/mapleall/maple_be/src/cg/cg_profile_use.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. All rights reverved. + * + * 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 "cg_profile_use.h" +#include "cg_critical_edge.h" +#include "optimize_common.h" + +namespace maplebe { +void CgProfUse::setupProf() { + FuncProfInfo *funcProf = cgFunc->GetFunction().GetFuncProfData(); + if (funcProf == nullptr) { + return; + } + + // Initialize all BBs with freq of stmts within it + FOR_ALL_BB(bb, cgFunc) { + bb->InitEdgeProfFreq(); + if (bb->GetFirstStmt() && + (static_cast(funcProf->GetStmtFreq(bb->GetFirstStmt()->GetStmtID())) > 0 )) { + bb->SetProfFreq(funcProf->GetStmtFreq(bb->GetFirstStmt()->GetStmtID())); + } else if (bb->GetLastStmt() && + (static_cast(funcProf->GetStmtFreq(bb->GetLastStmt()->GetStmtID())) > 0)) { + bb->SetProfFreq(funcProf->GetStmtFreq(bb->GetLastStmt()->GetStmtID())); + } else { +#if DEBUG + LogInfo::MapleLogger() << "BB" << bb->GetId() << " is not in execution path\n"; +#endif + } + + } + + // Propagate BB freq to edge freq + FOR_ALL_BB(bb, cgFunc) { + for (BB* succ : bb->GetSuccs()) { + (void) CreateEdge(bb, succ); + } + } + + for (Edge *e : GetAllEdges()) { + if (!(e->status) && (e->src->GetSuccs().size() == 1) && (e->src->GetProfFreq() != 0)) { + e->frequency = e->src->GetProfFreq(); + e->status = true; + } else if (!(e->status) && (e->dst->GetPreds().size() == 1) && (e->dst->GetProfFreq() != 0)) { + e->frequency = e->dst->GetProfFreq(); + e->status = true; + } + } + + SetupBB2Edges(); + + // Infer frequencies + InferEdgeFreq(); + + // Set freq on succs + SetSuccsFreq(); +} + +bool CGProfUse::PhaseRun(maplebe::CGFunc &f) { + CgProfUse cgprofuse(f, *GetPhaseMemPool()); + cgprofuse.setupProf(); + +#if DEBUG + LogInfo::MapleLogger() << "Setup CG ProfileUse : " << f.GetName() << "\n"; + DotGenerator::GenerateDot("CGProfUse", f, f.GetMirModule(), false, f.GetName()); +#endif + + return false; +} + +void CGProfUse::GetAnalysisDependence(maple::AnalysisDep &aDep) const { + //aDep.AddRequired(); +} + +MAPLE_ANALYSIS_PHASE_REGISTER_CANSKIP(CGProfUse, cgprofuse) +} diff --git a/src/mapleall/maple_be/src/cg/optimize_common.cpp b/src/mapleall/maple_be/src/cg/optimize_common.cpp index eba0636301..635f9e2bd7 100644 --- a/src/mapleall/maple_be/src/cg/optimize_common.cpp +++ b/src/mapleall/maple_be/src/cg/optimize_common.cpp @@ -137,10 +137,18 @@ void DotGenerator::DumpEdge(const CGFunc &cgFunction, std::ofstream &cfgFileOfSt cfgFileOfStream << "BB" << bb->GetId(); cfgFileOfStream << " -> " << "BB" << succBB->GetId(); - if (IsBackEdge(cgFunction, *bb, *succBB)) { - cfgFileOfStream << " [color=red]"; + if (Options::profileUse) { + if (IsBackEdge(cgFunction, *bb, *succBB)) { + cfgFileOfStream << " [color=red,label=" << bb->GetEdgeProfFreq(*succBB) << "]"; + } else { + cfgFileOfStream << " [color=green,label=" << bb->GetEdgeProfFreq(*succBB) << "]"; + } } else { - cfgFileOfStream << " [color=green]"; + if (IsBackEdge(cgFunction, *bb, *succBB)) { + cfgFileOfStream << " [color=red]"; + } else { + cfgFileOfStream << " [color=green]"; + } } cfgFileOfStream << ";\n"; } @@ -232,10 +240,18 @@ void DotGenerator::DumpBBInstructions(const CGFunc &cgFunction, regno_t vReg, st if (it != coloringMap.end()) { cfgFile << "style=filled,fillcolor=" << it->second << ","; } - if (bb->GetKind() == BB::kBBIf) { - cfgFile << "shape=diamond,label= \" BB" << bb->GetId() << ":\n"; + if (Options::profileUse) { + if (bb->GetKind() == BB::kBBIf) { + cfgFile << "shape=diamond,label= \" BB" << bb->GetId() << "_freq_" << bb->GetProfFreq() << ":\n"; + } else { + cfgFile << "shape=box,label= \" BB" << bb->GetId() << "_freq_" << bb->GetProfFreq() << ":\n"; + } } else { - cfgFile << "shape=box,label= \" BB" << bb->GetId() << ":\n"; + if (bb->GetKind() == BB::kBBIf) { + cfgFile << "shape=diamond,label= \" BB" << bb->GetId() << ":\n"; + } else { + cfgFile << "shape=box,label= \" BB" << bb->GetId() << ":\n"; + } } cfgFile << "{ "; cfgFile << bb->GetKindName() << "\n"; diff --git a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp index 073d9fd874..e363a99074 100644 --- a/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp +++ b/src/mapleall/maple_ipa/src/ipa_phase_manager.cpp @@ -103,7 +103,9 @@ void IpaSccPM::DoPhasesPopulate(const MIRModule &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); + if (!Options::profileUse) { + AddPhase("collect_ipa_info", true); + } AddPhase("sccsideeffect", Options::sideEffect); AddPhase("sccemit", true); } -- Gitee From 281162d979646a8a04c53a077303a98e7d4e8f13 Mon Sep 17 00:00:00 2001 From: fye Date: Wed, 30 Nov 2022 11:38:49 -0800 Subject: [PATCH 2/2] PGO: bring profile onto cg -- coding format improvement --- .../maple_be/include/cg/cg_profile_use.h | 29 +++++++++---------- .../maple_be/src/cg/cg_profile_use.cpp | 4 +-- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/cg_profile_use.h b/src/mapleall/maple_be/include/cg/cg_profile_use.h index 642f9a958f..5ae76a770c 100644 --- a/src/mapleall/maple_be/include/cg/cg_profile_use.h +++ b/src/mapleall/maple_be/include/cg/cg_profile_use.h @@ -20,20 +20,20 @@ namespace maplebe { class CgProfUse { - public: + public: struct Edge { - BB *src; - BB *dst; - Edge *next = nullptr; // the edge with the same src - uint64 frequency = 0; // later uint64_t - bool status = false; // True value indicates the edge's freq is determined - Edge(BB *bb1, BB *bb2) : src(bb1), dst(bb2) {} + BB *src; + BB *dst; + Edge *next = nullptr; // the edge with the same src + uint64 frequency = 0; // later int64_t + bool status = false; // True value indicates the edge's freq is determined + Edge(BB *bb1, BB *bb2) : src(bb1), dst(bb2) {} }; - CgProfUse(CGFunc &f, MemPool &mp) - : cgFunc(&f), memPool(&mp), alloc(&mp), allEdges(alloc.Adapter()), - BB2InEdges(alloc.Adapter()), BB2OutEdges(alloc.Adapter()) {} + CgProfUse(CGFunc &f, MemPool &mp) : + cgFunc(&f), memPool(&mp), alloc(&mp), allEdges(alloc.Adapter()), + BB2InEdges(alloc.Adapter()), BB2OutEdges(alloc.Adapter()) {} virtual ~CgProfUse() = default; @@ -95,7 +95,7 @@ class CgProfUse { Edge * unknownEdge1 = nullptr; MapleMap>::iterator iit = BB2InEdges.find(bb); if ((iit != BB2InEdges.end()) && (iit->second.size() != 0)) { - for (Edge *e : iit->second ) { + for (Edge *e : iit->second) { if (e->status) { knownEdges1++; freqSum1 += e->frequency; @@ -119,7 +119,7 @@ class CgProfUse { Edge * unknownEdge2 = nullptr; MapleMap>::iterator oit = BB2OutEdges.find(bb); if ((oit != BB2OutEdges.end()) && (oit->second.size() != 0)) { - for (Edge *e : oit->second ) { + for (Edge *e : oit->second) { if (e->status) { knownEdges2++; freqSum2 += e->frequency; @@ -161,18 +161,17 @@ class CgProfUse { bbQueue.push(unknownEdge2->dst); } } - } } - protected: + protected: CGFunc *cgFunc; MemPool *memPool; MapleAllocator alloc; MapleSet allEdges; MapleMap> BB2InEdges; MapleMap> BB2OutEdges; - private: + private: }; MAPLE_FUNC_PHASE_DECLARE(CGProfUse, maplebe::CGFunc) diff --git a/src/mapleall/maple_be/src/cg/cg_profile_use.cpp b/src/mapleall/maple_be/src/cg/cg_profile_use.cpp index 45bb9f075d..2bc7009757 100644 --- a/src/mapleall/maple_be/src/cg/cg_profile_use.cpp +++ b/src/mapleall/maple_be/src/cg/cg_profile_use.cpp @@ -27,7 +27,7 @@ void CgProfUse::setupProf() { FOR_ALL_BB(bb, cgFunc) { bb->InitEdgeProfFreq(); if (bb->GetFirstStmt() && - (static_cast(funcProf->GetStmtFreq(bb->GetFirstStmt()->GetStmtID())) > 0 )) { + (static_cast(funcProf->GetStmtFreq(bb->GetFirstStmt()->GetStmtID())) > 0)) { bb->SetProfFreq(funcProf->GetStmtFreq(bb->GetFirstStmt()->GetStmtID())); } else if (bb->GetLastStmt() && (static_cast(funcProf->GetStmtFreq(bb->GetLastStmt()->GetStmtID())) > 0)) { @@ -78,8 +78,8 @@ bool CGProfUse::PhaseRun(maplebe::CGFunc &f) { return false; } +//aDep.AddRequired(); // needed potentially void CGProfUse::GetAnalysisDependence(maple::AnalysisDep &aDep) const { - //aDep.AddRequired(); } MAPLE_ANALYSIS_PHASE_REGISTER_CANSKIP(CGProfUse, cgprofuse) -- Gitee