From bbe1595f92686b6c8cdd93d0f8148f77317144f7 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Tue, 28 Dec 2021 16:54:49 -0800 Subject: [PATCH 1/3] Various fixes so post-dominance analysis can be invoked; implemented cg_ssu_pre.cpp to perform placement optimization for the restores of callee-saved regs In aarch64_reg_alloc.cpp, added commented-out example code to exercise post-dominance analysis and SSUPRE. Make lfounroll skip loops with label definitions. --- src/mapleall/maple_be/BUILD.gn | 1 + src/mapleall/maple_be/include/cg/cg_cfg.h | 2 + .../maple_be/include/cg/cg_dominance.h | 19 + src/mapleall/maple_be/include/cg/cg_ssu_pre.h | 229 ++++++++ src/mapleall/maple_be/include/cg/cgbb.h | 7 + src/mapleall/maple_be/include/cg/cgfunc.h | 5 + .../src/cg/aarch64/aarch64_reg_alloc.cpp | 15 + src/mapleall/maple_be/src/cg/cg_cfg.cpp | 31 + src/mapleall/maple_be/src/cg/cg_dominance.cpp | 47 +- src/mapleall/maple_be/src/cg/cg_ssu_pre.cpp | 547 ++++++++++++++++++ src/mapleall/maple_be/src/cg/cgfunc.cpp | 27 + src/mapleall/maple_me/include/lfo_dep_test.h | 1 + src/mapleall/maple_me/src/lfo_dep_test.cpp | 5 + src/mapleall/maple_me/src/lfo_unroll.cpp | 2 +- 14 files changed, 935 insertions(+), 3 deletions(-) create mode 100644 src/mapleall/maple_be/include/cg/cg_ssu_pre.h create mode 100644 src/mapleall/maple_be/src/cg/cg_ssu_pre.cpp diff --git a/src/mapleall/maple_be/BUILD.gn b/src/mapleall/maple_be/BUILD.gn index 35224472fb..8c1ba14b64 100644 --- a/src/mapleall/maple_be/BUILD.gn +++ b/src/mapleall/maple_be/BUILD.gn @@ -180,6 +180,7 @@ src_libcg = [ "src/cg/cg_phi_elimination.cpp", "src/cg/reg_coalesce.cpp", "src/cg/alignment.cpp", + "src/cg/cg_ssu_pre.cpp", ] cflags_cc -= [ "-DRC_NO_MMAP" ] diff --git a/src/mapleall/maple_be/include/cg/cg_cfg.h b/src/mapleall/maple_be/include/cg/cg_cfg.h index 5daebc1f03..2cfcc2202a 100644 --- a/src/mapleall/maple_be/include/cg/cg_cfg.h +++ b/src/mapleall/maple_be/include/cg/cg_cfg.h @@ -108,6 +108,8 @@ class CGCFG { void FlushUnReachableStatusAndRemoveRelations(BB &curBB, const CGFunc &func) const; void MarkLabelTakenBB(); void UnreachCodeAnalysis(); + void FindWillExitBBs(BB *bb, std::set *visitedBBs); + void WontExitAnalysis(); BB *FindLastRetBB(); void UpdatePredsSuccsAfterSplit(BB &pred, BB &succ, BB &newBB); diff --git a/src/mapleall/maple_be/include/cg/cg_dominance.h b/src/mapleall/maple_be/include/cg/cg_dominance.h index cc5697f100..c442dc34db 100644 --- a/src/mapleall/maple_be/include/cg/cg_dominance.h +++ b/src/mapleall/maple_be/include/cg/cg_dominance.h @@ -170,6 +170,7 @@ class PostDomAnalysis : public DominanceBase { pdoms(bbVec.size() + 1, nullptr, domAllocator.Adapter()), pdomFrontier(bbVec.size() + 1, MapleVector(domAllocator.Adapter()), domAllocator.Adapter()), pdomChildren(bbVec.size() + 1, MapleVector(domAllocator.Adapter()), domAllocator.Adapter()), + iterPdomFrontier(bbVec.size() + 1, MapleSet(domAllocator.Adapter()), domAllocator.Adapter()), pdtPreOrder(bbVec.size() + 1, 0, domAllocator.Adapter()), pdtDfn(bbVec.size() + 1, -1, domAllocator.Adapter()), pdtDfnOut(bbVec.size() + 1, -1, domAllocator.Adapter()) {} @@ -180,6 +181,8 @@ class PostDomAnalysis : public DominanceBase { void ComputePostDominance(); void ComputePdomFrontiers(); void ComputePdomChildren(); + void GetIterPdomFrontier(const BB *bb, MapleSet *dfset, uint32 bbidMarker, std::vector &visitedMap); + void ComputeIterPdomFrontiers(); uint32 ComputePdtPreorder(const BB &bb, uint32 &num); bool PostDominate(const BB &bb1, const BB &bb2); // true if bb1 postdominates bb2 void Dump(); @@ -192,6 +195,10 @@ class PostDomAnalysis : public DominanceBase { return pdomFrontier.size(); } + auto &GetIpdomFrontier(uint32 idx) { + return iterPdomFrontier[idx]; + } + auto &GetPdomChildrenItem(size_t idx) { return pdomChildren[idx]; } @@ -204,6 +211,10 @@ class PostDomAnalysis : public DominanceBase { return pdtPreOrder[idx]; } + size_t GetPdtPreOrderSize() const { + return pdtPreOrder.size(); + } + uint32 GetPdtDfnItem(size_t idx) const { return pdtDfn[idx]; } @@ -246,6 +257,7 @@ class PostDomAnalysis : public DominanceBase { MapleVector pdoms; // index is bb id; immediate dominator for each BB MapleVector> pdomFrontier; // index is bb id MapleVector> pdomChildren; // index is bb id; for pdom tree + MapleVector> iterPdomFrontier; MapleVector pdtPreOrder; // ordering of the BBs in a preorder traversal of the post-dominator tree MapleVector pdtDfn; // gives position of each BB in pdt_preorder MapleVector pdtDfnOut; // max position of all nodes in the sub tree of each BB in pdt_preorder @@ -257,6 +269,13 @@ MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgDomAnalysis, maplebe::CGFunc); } DomAnalysis *domAnalysis = nullptr; MAPLE_FUNC_PHASE_DECLARE_END + +MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgPostDomAnalysis, maplebe::CGFunc); + PostDomAnalysis *GetResult() { + return pdomAnalysis; + } + PostDomAnalysis *pdomAnalysis = nullptr; +MAPLE_FUNC_PHASE_DECLARE_END } /* namespace maplebe */ #endif /* MAPLEBE_INCLUDE_CG_DOM_H */ diff --git a/src/mapleall/maple_be/include/cg/cg_ssu_pre.h b/src/mapleall/maple_be/include/cg/cg_ssu_pre.h new file mode 100644 index 0000000000..29a9db69ec --- /dev/null +++ b/src/mapleall/maple_be/include/cg/cg_ssu_pre.h @@ -0,0 +1,229 @@ +/* + * 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 MAPLEBE_CG_INCLUDE_CGSSUPRE_H +#define MAPLEBE_CG_INCLUDE_CGSSUPRE_H +#include +#include "mempool.h" +#include "mempool_allocator.h" +#include "cg_dominance.h" + +// Use SSUPRE to determine where to insert restores for callee-saved registers. +// The usage interface is DoRestorePlacementOpt(). Class SPreWorkCand is used +// as input/output interface. + +namespace maplebe { + +typedef uint32 BBId; + +// This must have been constructed by the caller of DoRestorePlacementOpt() and +// passed to it as parameter. The caller of DoRestorePlacementOpt() describes +// the problem via occBBs and saveBBs. DoRestorePlacementOpt()'s outputs are +// returned to the caller by setting restoreAtEntryBBs and restoreAtExitBBs. +class SPreWorkCand { + public: + SPreWorkCand(MapleAllocator *alloc): + occBBs(alloc->Adapter()), saveBBs(alloc->Adapter()), + restoreAtEntryBBs(alloc->Adapter()), restoreAtExitBBs(alloc->Adapter()) {} + // inputs + MapleSet occBBs; // Id's of BBs with appearances of the callee-saved reg + MapleSet saveBBs; // Id's of BBs with saves of the callee-saved reg + // outputs + MapleSet restoreAtEntryBBs; // Id's of BBs to insert restores of the register at BB entry + MapleSet restoreAtExitBBs; // Id's of BBs to insert restores of the register at BB exit +}; + +extern void DoRestorePlacementOpt(CGFunc *f, PostDomAnalysis *pdom, SPreWorkCand *workCand); + +enum SOccType { + kSOccUndef, + kSOccReal, + kSOccLambda, + kSOccLambdaRes, + kSOccEntry, + kSOccKill, +}; + +class SOcc { + public: + SOcc(SOccType ty, BB *bb) : occTy(ty), cgbb(bb) {} + virtual ~SOcc() = default; + + virtual void Dump() const = 0; + bool IsPostDominate(PostDomAnalysis *pdom, const SOcc *occ) const { + return pdom->PostDominate(*cgbb, *occ->cgbb); + } + + public: + SOccType occTy; + uint32 classId = 0; + BB *cgbb; // the BB it occurs in + SOcc *use = nullptr; // points to its single use +}; + +class SRealOcc : public SOcc { + public: + SRealOcc(BB *bb): SOcc(kSOccReal, bb) {} + virtual ~SRealOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "RealOcc at bb" << cgbb->GetId(); + LogInfo::MapleLogger() << " classId" << classId; + } + + public: + bool redundant = true; +}; + +class SLambdaOcc; + +class SLambdaResOcc : public SOcc { + public: + explicit SLambdaResOcc(BB *bb): SOcc(kSOccLambdaRes, bb) {} + virtual ~SLambdaResOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "LambdaResOcc at bb" << cgbb->GetId() << " classId" << classId; + } + + public: + SLambdaOcc *useLambdaOcc = nullptr; // its rhs use + bool hasRealUse = false; + bool insertHere = false; +}; + +class SLambdaOcc : public SOcc { + public: + SLambdaOcc(BB *bb, MapleAllocator &alloc) + : SOcc(kSOccLambda, bb), lambdaRes(alloc.Adapter()) {} + virtual ~SLambdaOcc() = default; + + bool WillBeAnt() const { + return isCanBeAnt && !isEarlier; + } + + void Dump() const { + LogInfo::MapleLogger() << "LambdaOcc at bb" << cgbb->GetId() << " classId" << classId << " Lambda["; + for (size_t i = 0; i < lambdaRes.size(); i++) { + lambdaRes[i]->Dump(); + if (i != lambdaRes.size() - 1) { + LogInfo::MapleLogger() << ", "; + } + } + LogInfo::MapleLogger() << "]"; + } + + public: + bool isUpsafe = true; + bool isCanBeAnt = true; + bool isEarlier = true; + MapleVector lambdaRes; +}; + +class SEntryOcc : public SOcc { + public: + explicit SEntryOcc(BB *bb) : SOcc(kSOccEntry, bb) {} + virtual ~SEntryOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "EntryOcc at bb" << cgbb->GetId(); + } +}; + +class SKillOcc : public SOcc { + public: + explicit SKillOcc(BB *bb) : SOcc(kSOccKill, bb) {} + virtual ~SKillOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "KillOcc at bb" << cgbb->GetId(); + } +}; + +class SSUPre { + public: + SSUPre(CGFunc *cgfunc, PostDomAnalysis *pd, MemPool *memPool, SPreWorkCand *wkcand, bool enDebug): + cgFunc(cgfunc), + pdom(pd), + spreMp(memPool), + spreAllocator(memPool), + workCand(wkcand), + realOccDfns(std::less(), spreAllocator.Adapter()), + lambdaDfns(std::less(), spreAllocator.Adapter()), + classCount(0), + realOccs(spreAllocator.Adapter()), + allOccs(spreAllocator.Adapter()), + lambdaOccs(spreAllocator.Adapter()), + entryOccs(spreAllocator.Adapter()), + enabledDebug(enDebug) { + CreateEntryOcc(cgfunc->GetFirstBB()); + } + ~SSUPre() = default; + + void ApplySSUPre(); + + private: + // step 6 methods + void CodeMotion(); + // step 5 methods + void Finalize(); + // step 4 methods + void ResetCanBeAnt(SLambdaOcc *lambda) const; + void ComputeCanBeAnt() const; + void ResetEarlier(SLambdaOcc *lambda) const; + void ComputeEarlier() const; + // step 3 methods + void ResetUpsafe(const SLambdaResOcc *lambdaRes) const; + void ComputeUpsafe() const; + // step 2 methods + void Rename(); + // step 1 methods + void GetIterPdomFrontier(const BB *bb, MapleSet *pdfset) const { + for (BBId bbid : pdom->GetIpdomFrontier(bb->GetId())) { + (void)pdfset->insert(pdom->GetPdtDfnItem(bbid)); + } + } + void FormLambdas(); + void FormLambdaRes(); + void CreateSortedOccs(); + // step 0 methods + void CreateEntryOcc(BB *bb) { + SEntryOcc *entryOcc = spreMp->New(bb); + entryOccs.push_back(entryOcc); + } + void FormReals(); + + CGFunc *cgFunc; + PostDomAnalysis *pdom; + MemPool *spreMp; + MapleAllocator spreAllocator; + SPreWorkCand *workCand; + // following are set of BBs in terms of their dfn's; index into + // dominance->pdt_preorder to get their bbid's + // step 0 + MapleSet realOccDfns; // set by FormReals() + // step 1 lambda insertion data structures: + MapleSet lambdaDfns; // set by FormLambdas() + // step 2 renaming + uint32 classCount; // for assigning new class id + // the following 4 lists are all maintained in order of pdt_preorder + MapleVector realOccs; // both real and kill occurrences + MapleVector allOccs; + MapleVector lambdaOccs; + MapleVector entryOccs; + bool enabledDebug; +}; + +}; // namespace maplabe +#endif // MAPLEBE_CG_INCLUDE_CGSSUPRE_H diff --git a/src/mapleall/maple_be/include/cg/cgbb.h b/src/mapleall/maple_be/include/cg/cgbb.h index c7b1fb4ad2..4fa089fad5 100644 --- a/src/mapleall/maple_be/include/cg/cgbb.h +++ b/src/mapleall/maple_be/include/cg/cgbb.h @@ -524,6 +524,12 @@ class BB { void SetUnreachable(bool arg) { unreachable = arg; } + bool IsWontExit() const { + return wontExit; + } + void SetWontExit(bool arg) { + wontExit = arg; + } void SetFastPath(bool arg) { fastPath = arg; } @@ -756,6 +762,7 @@ class BB { bool insertUse = false; bool hasCall = false; bool unreachable = false; + bool wontExit = false; bool fastPath = false; bool isCatch = false; /* part of the catch bb, true does might also mean it is unreachable */ /* diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index d665bcadb5..88c4641c3b 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -677,6 +677,10 @@ class CGFunc { return dummyBB; } + BB *GetCommonExitBB() { + return commonExitBB; + } + LabelIdx GetFirstCGGenLabelIdx() const { return firstCGGenLabelIdx; } @@ -1134,6 +1138,7 @@ class CGFunc { BB *lastBB = nullptr; BB *curBB = nullptr; BB *dummyBB; /* use this bb for add some instructions to bb that is no curBB. */ + BB *commonExitBB = nullptr; /* this post-dominate all BBs */ Insn *volReleaseInsn = nullptr; /* use to record the release insn for volatile strore */ MapleVector exitBBVec; MapleSet extendSet; /* use to mark regs which spilled 32 bits but loaded 64 bits. */ diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp index ca714ffa60..c7ef8511b1 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp @@ -20,6 +20,7 @@ #include "cg_dominance.h" #include "mir_lower.h" #include "securec.h" +#include "cg_ssu_pre.h" namespace maplebe { /* @@ -603,6 +604,20 @@ bool CgRegAlloc::PhaseRun(maplebe::CGFunc &f) { } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLiveAnalysis::id); } +#if 0 // for exercising postdominance analysis and DoRestorePlacementOpt() + PostDomAnalysis *pdom = nullptr; + MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( + &CgPostDomAnalysis::id, f); + pdom = static_cast(it)->GetResult(); + CHECK_FATAL(pdom != nullptr, "null ptr check"); + MemPool *phaseMp = GetPhaseMemPool(); + MapleAllocator sprealloc(phaseMp); + SPreWorkCand wkCand(&sprealloc); + // initialize the inputs here, e.g. + // wkCand.saveBBs.insert(2); + // wkCand.occBBs.insert(9); + DoRestorePlacementOpt(&f, pdom, &wkCand); +#endif GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLoopAnalysis::id); return false; } diff --git a/src/mapleall/maple_be/src/cg/cg_cfg.cpp b/src/mapleall/maple_be/src/cg/cg_cfg.cpp index 6acd8ad157..d51f144c84 100644 --- a/src/mapleall/maple_be/src/cg/cg_cfg.cpp +++ b/src/mapleall/maple_be/src/cg/cg_cfg.cpp @@ -686,6 +686,37 @@ void CGCFG::UnreachCodeAnalysis() { } } +void CGCFG::FindWillExitBBs(BB *bb, std::set *visitedBBs) { + if (visitedBBs->count(bb) != 0) { + return; + } + visitedBBs->insert(bb); + for (BB *predbb : bb->GetPreds()) { + FindWillExitBBs(predbb, visitedBBs); + } +} + +/* + * analyse the CFG to find the BBs that will not reach any function exit; these + * are BBs inside infinite loops; mark their wontExit flag and create + * artificial edges from them to commonExitBB + */ +void CGCFG::WontExitAnalysis() { + std::set visitedBBs; + FindWillExitBBs(cgFunc->GetCommonExitBB(), &visitedBBs); + BB *bb = cgFunc->GetFirstBB(); + while (bb != nullptr) { + if (visitedBBs.count(bb) == 0) { + bb->SetWontExit(true); + if (bb->GetKind() == BB::kBBGoto || bb->GetKind() == BB::kBBThrow) { + // make this bb a predecessor of commonExitBB + cgFunc->GetCommonExitBB()->PushBackPreds(*bb); + } + } + bb = bb->GetNext(); + } +} + BB *CGCFG::FindLastRetBB() { FOR_ALL_BB_REV(bb, cgFunc) { if (bb->GetKind() == BB::kBBReturn) { diff --git a/src/mapleall/maple_be/src/cg/cg_dominance.cpp b/src/mapleall/maple_be/src/cg/cg_dominance.cpp index 92bc2d80fc..a3383623e0 100644 --- a/src/mapleall/maple_be/src/cg/cg_dominance.cpp +++ b/src/mapleall/maple_be/src/cg/cg_dominance.cpp @@ -314,7 +314,8 @@ void PostDomAnalysis::ComputePostDominance() { BB *bb = pdomReversePostOrder[i]; BB *suc = nullptr; auto it = bb->GetSuccsBegin(); - if (cgFunc.IsExitBB(*bb) || bb->GetSuccs().empty()) { + if (cgFunc.IsExitBB(*bb) || bb->GetSuccs().empty() || + (bb->IsWontExit() && bb->GetKind() == BB::kBBGoto)) { suc = &commonExitBB; } else { suc = *it; @@ -378,6 +379,35 @@ void PostDomAnalysis::ComputePdomChildren() { } } +// bbidMarker indicates that the iterPdomFrontier results for bbid < bbidMarker +// have been computed +void PostDomAnalysis::GetIterPdomFrontier(const BB *bb, MapleSet *dfset, uint32 bbidMarker, + std::vector &visitedMap) { + if (visitedMap[bb->GetId()]) { + return; + } + visitedMap[bb->GetId()] = true; + for (uint32 frontierbbid : pdomFrontier[bb->GetId()]) { + (void)dfset->insert(frontierbbid); + if (frontierbbid < bbidMarker) { // union with its computed result + dfset->insert(iterPdomFrontier[frontierbbid].begin(), iterPdomFrontier[frontierbbid].end()); + } else { // recursive call + BB *frontierbb = bbVec[frontierbbid]; + GetIterPdomFrontier(frontierbb, dfset, bbidMarker, visitedMap); + } + } +} + +void PostDomAnalysis::ComputeIterPdomFrontiers() { + for (BB *bb : bbVec) { + if (bb == nullptr || bb == &commonEntryBB) { + continue; + } + std::vector visitedMap(bbVec.size(), false); + GetIterPdomFrontier(bb, &iterPdomFrontier[bb->GetId()], bb->GetId(), visitedMap); + } +} + uint32 PostDomAnalysis::ComputePdtPreorder(const BB &bb, uint32 &num) { ASSERT(num < pdtPreOrder.size(), "index out of range in Dominance::ComputePdtPreOrder"); pdtPreOrder[num] = bb.GetId(); @@ -426,6 +456,7 @@ void PostDomAnalysis::Compute() { ComputePostDominance(); ComputePdomFrontiers(); ComputePdomChildren(); + ComputeIterPdomFrontiers(); uint32 num = 0; (void)ComputePdtPreorder(GetCommonExitBB(), num); ResizePdtPreOrder(num); @@ -434,7 +465,7 @@ void PostDomAnalysis::Compute() { bool CgDomAnalysis::PhaseRun(maplebe::CGFunc &f) { MemPool *domMemPool = GetPhaseMemPool(); domAnalysis = domMemPool->New(f, *domMemPool, *domMemPool, f.GetAllBBs(), - *f.GetFirstBB(), *f.GetLastBB()); + *f.GetFirstBB(), *f.GetCommonExitBB()); domAnalysis->Compute(); if (CG_DEBUG_FUNC(f)) { domAnalysis->Dump(); @@ -442,4 +473,16 @@ bool CgDomAnalysis::PhaseRun(maplebe::CGFunc &f) { return false; } MAPLE_ANALYSIS_PHASE_REGISTER(CgDomAnalysis, domanalysis) + +bool CgPostDomAnalysis::PhaseRun(maplebe::CGFunc &f) { + MemPool *pdomMemPool = GetPhaseMemPool(); + pdomAnalysis = pdomMemPool->New(f, *pdomMemPool, *pdomMemPool, f.GetAllBBs(), + *f.GetFirstBB(), *f.GetCommonExitBB()); + pdomAnalysis->Compute(); + if (CG_DEBUG_FUNC(f)) { + pdomAnalysis->Dump(); + } + return false; +} +MAPLE_ANALYSIS_PHASE_REGISTER(CgPostDomAnalysis, pdomanalysis) } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/src/cg/cg_ssu_pre.cpp b/src/mapleall/maple_be/src/cg/cg_ssu_pre.cpp new file mode 100644 index 0000000000..0f4671ef5a --- /dev/null +++ b/src/mapleall/maple_be/src/cg/cg_ssu_pre.cpp @@ -0,0 +1,547 @@ +/* + * 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. + */ +#include "cgfunc.h" +#include "cg_ssu_pre.h" + +namespace maplebe { + +// ================ Step 6: Code Motion ================ +void SSUPre::CodeMotion() { + // pass 1 only donig insertion + for (SOcc *occ : allOccs) { + if (occ->occTy != kSOccLambdaRes) { + continue; + } + SLambdaResOcc *lambdaResOcc = static_cast(occ); + if (lambdaResOcc->insertHere) { + workCand->restoreAtEntryBBs.insert(lambdaResOcc->cgbb->GetId()); + } + } + // pass 2 only doing deletion + for (SOcc *occ : realOccs) { + if (occ->occTy != kSOccReal) { + continue; + } + SRealOcc *realOcc = static_cast(occ); + if (!realOcc->redundant) { + workCand->restoreAtExitBBs.insert(realOcc->cgbb->GetId()); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ output _______" << '\n'; + LogInfo::MapleLogger() << " restoreAtEntryBBs: ["; + for (uint32 id : workCand->restoreAtEntryBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n restoreAtExitBBs: ["; + for (uint32 id : workCand->restoreAtExitBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n\n"; + } +} + +// ================ Step 5: Finalize ================ +// for setting SRealOcc's redundant flag and SLambdaResOcc's insertHere flag +void SSUPre::Finalize() { + std::vector anticipatedDefVec(classCount + 1, nullptr); + // preorder traversal of post-dominator tree + for (SOcc *occ : allOccs) { + size_t classId = static_cast(occ->classId); + switch (occ->occTy) { + case kSOccLambda: { + auto *lambdaOcc = static_cast(occ); + if (lambdaOcc->WillBeAnt()) { + anticipatedDefVec[classId] = lambdaOcc; + } + break; + } + case kSOccReal: { + auto *realOcc = static_cast(occ); + if (anticipatedDefVec[classId] == nullptr || !anticipatedDefVec[classId]->IsPostDominate(pdom, occ)) { + realOcc->redundant = false; + anticipatedDefVec[classId] = realOcc; + } else { + realOcc->redundant = true; + } + break; + } + case kSOccLambdaRes: { + auto *lambdaResOcc = static_cast(occ); + const SLambdaOcc *lambdaOcc = lambdaResOcc->useLambdaOcc; + if (lambdaOcc->WillBeAnt()) { + if (lambdaResOcc->use == nullptr || (!lambdaResOcc->hasRealUse && + lambdaResOcc->use->occTy == kSOccLambda && + !static_cast(lambdaResOcc->use)->WillBeAnt())) { + // insert a store + if (lambdaResOcc->cgbb->GetPreds().size() != 1) { // critical edge + CHECK_FATAL(false, "SSUPre::Finalize: insertion at critical edge"); + } + lambdaResOcc->insertHere = true; + } else { + lambdaResOcc->use = anticipatedDefVec[classId]; + } + } + break; + } + case kSOccEntry: + case kSOccKill: + break; + default: + ASSERT(false, "Finalize: unexpected occ type"); + break; + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after finalize _______" << '\n'; + for (SOcc *occ : allOccs) { + if (occ->occTy == kSOccReal) { + SRealOcc *realOcc = static_cast(occ); + if (!realOcc->redundant) { + occ->Dump(); + LogInfo::MapleLogger() << " non-redundant" << '\n'; + } + } else if (occ->occTy == kSOccLambdaRes) { + SLambdaResOcc *lambdaResOcc = static_cast(occ); + if (lambdaResOcc->insertHere) { + occ->Dump(); + LogInfo::MapleLogger() << " insertHere" << '\n'; + } + } + } + } +} + +// ================ Step 4: WillBeAnt Computation ================ + +void SSUPre::ResetCanBeAnt(SLambdaOcc *lambda) const { + lambda->isCanBeAnt = false; + // the following loop finds lambda's defs and reset them + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + for (SLambdaResOcc *lambdaResOcc : lambdaOcc->lambdaRes) { + if (lambdaResOcc->use != nullptr && lambdaResOcc->use == lambda) { + if (!lambdaResOcc->hasRealUse && !lambdaOcc->isUpsafe && lambdaOcc->isCanBeAnt) { + ResetCanBeAnt(lambdaOcc); + } + } + } + } +} + +void SSUPre::ComputeCanBeAnt() const { + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + if (!lambdaOcc->isUpsafe && lambdaOcc->isCanBeAnt) { + bool existNullUse = false; + for (SLambdaResOcc *lambdaResOcc : lambdaOcc->lambdaRes) { + if (lambdaResOcc->use == nullptr) { + existNullUse = true; + break; + } + } + if (existNullUse) { + ResetCanBeAnt(lambdaOcc); + } + } + } +} + +void SSUPre::ResetEarlier(SLambdaOcc *lambda) const { + lambda->isEarlier = false; + // the following loop finds lambda's defs and reset them + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + for (SLambdaResOcc *lambdaResOcc : lambdaOcc->lambdaRes) { + if (lambdaResOcc->use != nullptr && lambdaResOcc->use == lambda) { + if (lambdaOcc->isEarlier) { + ResetEarlier(lambdaOcc); + } + } + } + } +} + +void SSUPre::ComputeEarlier() const { + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + lambdaOcc->isEarlier = lambdaOcc->isCanBeAnt; + } + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + if (lambdaOcc->isEarlier) { + bool existNonNullUse = false; + for (SLambdaResOcc *lambdaResOcc : lambdaOcc->lambdaRes) { + if (lambdaResOcc->use != nullptr && lambdaResOcc->hasRealUse) { + existNonNullUse = true; + break; + } + } + if (existNonNullUse) { + ResetEarlier(lambdaOcc); + } + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after earlier computation _______" << '\n'; + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + lambdaOcc->Dump(); + if (lambdaOcc->isCanBeAnt) { + LogInfo::MapleLogger() << " canbeant"; + } + if (lambdaOcc->isEarlier) { + LogInfo::MapleLogger() << " earlier"; + } + if (lambdaOcc->isCanBeAnt && !lambdaOcc->isEarlier) { + LogInfo::MapleLogger() << " will be ant"; + } + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 3: Upsafe Computation ================ +void SSUPre::ResetUpsafe(const SLambdaResOcc *lambdaRes) const { + if (lambdaRes->hasRealUse) { + return; + } + SOcc *useOcc = lambdaRes->use; + if (useOcc == nullptr || useOcc->occTy != kSOccLambda) { + return; + } + auto *useLambdaOcc = static_cast(useOcc); + if (!useLambdaOcc->isUpsafe) { + return; + } + useLambdaOcc->isUpsafe = false; + for (SLambdaResOcc *lambdaResOcc : useLambdaOcc->lambdaRes) { + ResetUpsafe(lambdaResOcc); + } +} + +void SSUPre::ComputeUpsafe() const { + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + if (!lambdaOcc->isUpsafe) { + // propagate not-upsafe forward along def-use edges + for (SLambdaResOcc *lambdaResOcc : lambdaOcc->lambdaRes) { + ResetUpsafe(lambdaResOcc); + } + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after upsafe computation _______" << '\n'; + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + lambdaOcc->Dump(); + if (lambdaOcc->isUpsafe) { + LogInfo::MapleLogger() << " upsafe"; + } + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 2: rename ================ +void SSUPre::Rename() { + std::stack occStack; + classCount = 0; + // iterate thru the occurrences in order of preorder traversal of + // post-dominator tree + for (SOcc *occ : allOccs) { + while (!occStack.empty() && !occStack.top()->IsPostDominate(pdom, occ)) { + occStack.pop(); + } + switch (occ->occTy) { + case kSOccKill: + if (!occStack.empty()) { + SOcc *topOcc = occStack.top(); + if (topOcc->occTy == kSOccLambda) { + static_cast(topOcc)->isUpsafe = false; + } + } + occStack.push(occ); + break; + case kSOccEntry: + if (!occStack.empty()) { + SOcc *topOcc = occStack.top(); + if (topOcc->occTy == kSOccLambda) { + static_cast(topOcc)->isUpsafe = false; + } + } + break; + case kSOccLambda: + // assign new class + occ->classId = ++classCount; + occStack.push(occ); + break; + case kSOccReal: { + if (occStack.empty()) { + // assign new class + occ->classId = ++classCount; + occStack.push(occ); + break; + } + SOcc *topOcc = occStack.top(); + if (topOcc->occTy == kSOccKill) { + // assign new class + occ->classId = ++classCount; + occStack.push(occ); + break; + } + ASSERT(topOcc->occTy == kSOccLambda || topOcc->occTy == kSOccReal, + "Rename: unexpected top-of-stack occ"); + occ->classId = topOcc->classId; + if (topOcc->occTy == kSOccLambda) { + occStack.push(occ); + } + break; + } + case kSOccLambdaRes: { + if (occStack.empty()) { + // leave classId as 0 + break; + } + SOcc *topOcc = occStack.top(); + if (topOcc->occTy == kSOccKill) { + // leave classId as 0 + break; + } + ASSERT(topOcc->occTy == kSOccLambda || topOcc->occTy == kSOccReal, + "Rename: unexpected top-of-stack occ"); + occ->use = topOcc; + occ->classId = topOcc->classId; + if (topOcc->occTy == kSOccReal) { + static_cast(occ)->hasRealUse = true; + } + break; + } + default: + ASSERT(false, "Rename: unexpected type of occurrence"); + break; + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after rename _______" << '\n'; + for (SOcc *occ : allOccs) { + occ->Dump(); + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 1: insert lambdas ================ + +// form lambda occ based on the real occ in workCand->realOccs; result is +// stored in lambdaDfns +void SSUPre::FormLambdas() { + for (SOcc *occ : realOccs) { + if (occ->occTy == kSOccKill) { + continue; + } + GetIterPdomFrontier(occ->cgbb, &lambdaDfns); + } +} + +// form allOccs inclusive of real, kill, lambda, lambdaRes, entry occurrences; +// form lambdaOccs containing only the lambdas +void SSUPre::CreateSortedOccs() { + // form lambdaRes occs based on the succs of the lambda occs; result is + // stored in lambdaResDfns + std::multiset lambdaResDfns; + for (uint32 dfn : lambdaDfns) { + const BBId bbId = pdom->GetPdtPreOrderItem(dfn); + BB *cgbb = cgFunc->GetAllBBs()[bbId]; + for (BB *succ : cgbb->GetSuccs()) { + (void)lambdaResDfns.insert(pdom->GetPdtDfnItem(succ->GetId())); + } + } + std::unordered_map> bb2LambdaResMap; + MapleVector::iterator realOccIt = realOccs.begin(); + MapleVector::iterator entryOccIt = entryOccs.begin(); + MapleSet::iterator lambdaDfnIt = lambdaDfns.begin(); + MapleSet::iterator lambdaResDfnIt = lambdaResDfns.begin(); + SOcc *nextRealOcc = nullptr; + if (realOccIt != realOccs.end()) { + nextRealOcc = *realOccIt; + } + SEntryOcc *nextEntryOcc = nullptr; + if (entryOccIt != entryOccs.end()) { + nextEntryOcc = *entryOccIt; + } + SLambdaOcc *nextLambdaOcc = nullptr; + if (lambdaDfnIt != lambdaDfns.end()) { + nextLambdaOcc = + spreMp->New(cgFunc->GetAllBBs().at(pdom->GetPdtPreOrderItem(*lambdaDfnIt)), spreAllocator); + } + SLambdaResOcc *nextLambdaResOcc = nullptr; + if (lambdaResDfnIt != lambdaResDfns.end()) { + nextLambdaResOcc = spreMp->New(cgFunc->GetAllBBs().at(pdom->GetPdtPreOrderItem(*lambdaResDfnIt))); + auto it = bb2LambdaResMap.find(pdom->GetPdtPreOrderItem(*lambdaResDfnIt)); + if (it == bb2LambdaResMap.end()) { + std::forward_list newlist = { nextLambdaResOcc }; + bb2LambdaResMap[pdom->GetPdtPreOrderItem(*lambdaResDfnIt)] = newlist; + } else { + it->second.push_front(nextLambdaResOcc); + } + } + SOcc *pickedOcc = nullptr; // the next picked occ in order of preorder traversal of post-dominator tree + do { + pickedOcc = nullptr; + if (nextLambdaOcc != nullptr) { + pickedOcc = nextLambdaOcc; + } + if (nextRealOcc != nullptr && (pickedOcc == nullptr || pdom->GetPdtDfnItem(nextRealOcc->cgbb->GetId()) < + pdom->GetPdtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextRealOcc; + } + if (nextLambdaResOcc != nullptr && + (pickedOcc == nullptr || *lambdaResDfnIt < pdom->GetPdtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextLambdaResOcc; + } + if (nextEntryOcc != nullptr && (pickedOcc == nullptr || pdom->GetPdtDfnItem(nextEntryOcc->cgbb->GetId()) < + pdom->GetPdtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextEntryOcc; + } + if (pickedOcc != nullptr) { + allOccs.push_back(pickedOcc); + switch (pickedOcc->occTy) { + case kSOccReal: + case kSOccKill: + // get the next real/kill occ + CHECK_FATAL(realOccIt != realOccs.end(), "iterator check"); + ++realOccIt; + if (realOccIt != realOccs.end()) { + nextRealOcc = *realOccIt; + } else { + nextRealOcc = nullptr; + } + break; + case kSOccEntry: + CHECK_FATAL(entryOccIt != entryOccs.end(), "iterator check"); + ++entryOccIt; + if (entryOccIt != entryOccs.end()) { + nextEntryOcc = *entryOccIt; + } else { + nextEntryOcc = nullptr; + } + break; + case kSOccLambda: + lambdaOccs.push_back(static_cast(pickedOcc)); + CHECK_FATAL(lambdaDfnIt != lambdaDfns.end(), "iterator check"); + ++lambdaDfnIt; + if (lambdaDfnIt != lambdaDfns.end()) { + nextLambdaOcc = + spreMp->New(cgFunc->GetAllBBs().at(pdom->GetPdtPreOrderItem(*lambdaDfnIt)), spreAllocator); + } else { + nextLambdaOcc = nullptr; + } + break; + case kSOccLambdaRes: + CHECK_FATAL(lambdaResDfnIt != lambdaResDfns.end(), "iterator check"); + ++lambdaResDfnIt; + if (lambdaResDfnIt != lambdaResDfns.end()) { + nextLambdaResOcc = + spreMp->New(cgFunc->GetAllBBs().at(pdom->GetPdtPreOrderItem(*lambdaResDfnIt))); + auto it = bb2LambdaResMap.find(pdom->GetPdtPreOrderItem(*lambdaResDfnIt)); + if (it == bb2LambdaResMap.end()) { + std::forward_list newlist = { nextLambdaResOcc }; + bb2LambdaResMap[pdom->GetPdtPreOrderItem(*lambdaResDfnIt)] = newlist; + } else { + it->second.push_front(nextLambdaResOcc); + } + } else { + nextLambdaResOcc = nullptr; + } + break; + default: + ASSERT(false, "CreateSortedOccs: unexpected occTy"); + break; + } + } + } while (pickedOcc != nullptr); + // initialize lambdaRes vector in each SLambdaOcc node and useLambdaOcc in each SLambdaResOcc + for (SLambdaOcc *lambdaOcc : lambdaOccs) { + for (BB *succ : lambdaOcc->cgbb->GetSuccs()) { + SLambdaResOcc *lambdaResOcc = bb2LambdaResMap[succ->GetId()].front(); + lambdaOcc->lambdaRes.push_back(lambdaResOcc); + lambdaResOcc->useLambdaOcc = lambdaOcc; + bb2LambdaResMap[succ->GetId()].pop_front(); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after lambda insertion _______" << '\n'; + for (SOcc *occ : allOccs) { + occ->Dump(); + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 0: Preparations ================ + +void SSUPre::FormReals() { + for (uint32 i = 0; i < pdom->GetPdtPreOrderSize(); i++) { + uint32 bbid = pdom->GetPdtPreOrderItem(i); + BB *cgbb = cgFunc->GetAllBBs()[bbid]; + if (workCand->saveBBs.count(cgbb->GetId()) != 0) { + SRealOcc *realOcc = spreMp->New(cgbb); + realOccs.push_back(realOcc); + SKillOcc *killOcc = spreMp->New(cgbb); + realOccs.push_back(killOcc); + } else if (workCand->occBBs.count(cgbb->GetId()) != 0) { + SRealOcc *realOcc = spreMp->New(cgbb); + realOccs.push_back(realOcc); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << "Placement Optimization for callee-save restores" << '\n'; + LogInfo::MapleLogger() << "-----------------------------------------------" << '\n'; + LogInfo::MapleLogger() << " _______ input _______" << '\n'; + LogInfo::MapleLogger() << " occBBs: ["; + for (uint32 id : workCand->occBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n saveBBs: ["; + for (uint32 id : workCand->saveBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n"; + } +} + +void SSUPre::ApplySSUPre() { + FormReals(); + // #1 insert lambdas; results in allOccs and lambdaOccs + FormLambdas(); // result put in the set lambda_bbs + CreateSortedOccs(); + // #2 rename + Rename(); + if (!lambdaOccs.empty()) { + // #3 UpSafety + ComputeUpsafe(); + // #4 CanBeAnt + ComputeCanBeAnt(); + ComputeEarlier(); + } + // #5 Finalize + Finalize(); + // #6 Code Motion + CodeMotion(); +} + +void DoRestorePlacementOpt(CGFunc *f, PostDomAnalysis *pdom, SPreWorkCand *workCand) { + MemPool *tempMP = memPoolCtrler.NewMemPool("cg_ssu_pre", true); + SSUPre cgssupre(f, pdom, tempMP, workCand, false/*enabledDebug*/); + + cgssupre.ApplySSUPre(); + + memPoolCtrler.DeleteMemPool(tempMP); +} + +} // namespace maplebe diff --git a/src/mapleall/maple_be/src/cg/cgfunc.cpp b/src/mapleall/maple_be/src/cg/cgfunc.cpp index eb470d0315..66dfee1fac 100644 --- a/src/mapleall/maple_be/src/cg/cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/cgfunc.cpp @@ -1692,6 +1692,7 @@ void CGFunc::ProcessExitBBVec() { BB *retBB = CreateNewBB(newLabelIdx, cleanupBB->IsUnreachable(), BB::kBBReturn, cleanupBB->GetFrequency()); cleanupBB->PrependBB(*retBB); exitBBVec.emplace_back(retBB); + commonExitBB = retBB; return; } /* split an empty exitBB */ @@ -1715,6 +1716,31 @@ void CGFunc::ProcessExitBBVec() { bb->AddLabel(newLabelIdx); lab2BBMap[newLabelIdx] = bb; } + /* set commonExitBB */ + uint32 i = 0; + while (exitBBVec[i]->IsUnreachable() && i < exitBBVec.size()) { + i++; + } + ASSERT(i < exitBBVec.size(), "all exit BBs are unreacable"); + commonExitBB = exitBBVec[i]; + bool multipleExitBBs = false; + i++; + while (i < exitBBVec.size()) { + if (!exitBBVec[i]->IsUnreachable()) { + multipleExitBBs = true; + break; + } + i++; + } + if (multipleExitBBs) { // create fake commonExitBB + commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0); + ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB"); + for (BB *cgbb : exitBBVec) { + if (!cgbb->IsUnreachable()) { + commonExitBB->PushBackPreds(*cgbb); + } + } + } } void CGFunc::UpdateCallBBFrequency() { @@ -1762,6 +1788,7 @@ void CGFunc::HandleFunction() { DetermineReturnTypeofCall(); theCFG->MarkLabelTakenBB(); theCFG->UnreachCodeAnalysis(); + theCFG->WontExitAnalysis(); SplitStrLdrPair(); if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) { ProcessLazyBinding(); diff --git a/src/mapleall/maple_me/include/lfo_dep_test.h b/src/mapleall/maple_me/include/lfo_dep_test.h index 6adea69ca7..9e60ef9746 100644 --- a/src/mapleall/maple_me/include/lfo_dep_test.h +++ b/src/mapleall/maple_me/include/lfo_dep_test.h @@ -78,6 +78,7 @@ class DoloopInfo { bool hasScalarAssign = false; // give up dep testing if true bool hasMayDef = false; // give up dep testing if true bool hasBeenVectorized = false; // set by loopvec phase + bool hasLabels = false; // needed by lfounroll phase MapleVector outputDepTestList; // output dependence only MapleVector flowDepTestList; // include both true and anti dependences MapleSet redVars; // reduction variables diff --git a/src/mapleall/maple_me/src/lfo_dep_test.cpp b/src/mapleall/maple_me/src/lfo_dep_test.cpp index 605e0a0df9..8c6da8f09f 100644 --- a/src/mapleall/maple_me/src/lfo_dep_test.cpp +++ b/src/mapleall/maple_me/src/lfo_dep_test.cpp @@ -73,6 +73,11 @@ void LfoDepInfo::CreateDoloopInfo(BlockNode *block, DoloopInfo *parent) { parent->hasOtherCtrlFlow = true; } break; + case OP_label: + if (parent) { + parent->hasLabels = true; + } + break; default: break; } diff --git a/src/mapleall/maple_me/src/lfo_unroll.cpp b/src/mapleall/maple_me/src/lfo_unroll.cpp index 9d24821727..5a083fa03e 100644 --- a/src/mapleall/maple_me/src/lfo_unroll.cpp +++ b/src/mapleall/maple_me/src/lfo_unroll.cpp @@ -189,7 +189,7 @@ static size_t CountBlockStmts(BlockNode *blk) { } void LfoUnrollOneLoop::Process() { - if (doloopInfo->hasOtherCtrlFlow || doloopInfo->hasBeenVectorized) { + if (doloopInfo->hasOtherCtrlFlow || doloopInfo->hasBeenVectorized || doloopInfo->hasLabels) { return; } if (!doloop->GetIncrExpr()->IsConstval()) { -- Gitee From 82de307d3e95a54bde82afd52d1832922b2e0ae3 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Tue, 28 Dec 2021 18:42:59 -0800 Subject: [PATCH 2/3] Only perform post-dominance analysis and related CFG changes when language is C --- .../src/cg/aarch64/aarch64_reg_alloc.cpp | 26 ++++++++++--------- src/mapleall/maple_be/src/cg/cgfunc.cpp | 4 ++- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp index c7ef8511b1..a02275ab7a 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp @@ -605,18 +605,20 @@ bool CgRegAlloc::PhaseRun(maplebe::CGFunc &f) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLiveAnalysis::id); } #if 0 // for exercising postdominance analysis and DoRestorePlacementOpt() - PostDomAnalysis *pdom = nullptr; - MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( - &CgPostDomAnalysis::id, f); - pdom = static_cast(it)->GetResult(); - CHECK_FATAL(pdom != nullptr, "null ptr check"); - MemPool *phaseMp = GetPhaseMemPool(); - MapleAllocator sprealloc(phaseMp); - SPreWorkCand wkCand(&sprealloc); - // initialize the inputs here, e.g. - // wkCand.saveBBs.insert(2); - // wkCand.occBBs.insert(9); - DoRestorePlacementOpt(&f, pdom, &wkCand); + if (f.GetMirModule().GetSrcLang() == kSrcLangC) { + PostDomAnalysis *pdom = nullptr; + MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( + &CgPostDomAnalysis::id, f); + pdom = static_cast(it)->GetResult(); + CHECK_FATAL(pdom != nullptr, "null ptr check"); + MemPool *phaseMp = GetPhaseMemPool(); + MapleAllocator sprealloc(phaseMp); + SPreWorkCand wkCand(&sprealloc); + // initialize the inputs here, e.g. + // wkCand.saveBBs.insert(2); + // wkCand.occBBs.insert(9); + DoRestorePlacementOpt(&f, pdom, &wkCand); + } #endif GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLoopAnalysis::id); return false; diff --git a/src/mapleall/maple_be/src/cg/cgfunc.cpp b/src/mapleall/maple_be/src/cg/cgfunc.cpp index 66dfee1fac..a3cf82aa79 100644 --- a/src/mapleall/maple_be/src/cg/cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/cgfunc.cpp @@ -1788,7 +1788,9 @@ void CGFunc::HandleFunction() { DetermineReturnTypeofCall(); theCFG->MarkLabelTakenBB(); theCFG->UnreachCodeAnalysis(); - theCFG->WontExitAnalysis(); + if (mirModule.GetSrcLang() == kSrcLangC) { + theCFG->WontExitAnalysis(); + } SplitStrLdrPair(); if (CGOptions::IsLazyBinding() && !GetCG()->IsLibcore()) { ProcessLazyBinding(); -- Gitee From 1f4d837009e7aae06dec7fd83cde492796b102d2 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Thu, 30 Dec 2021 05:04:55 -0800 Subject: [PATCH 3/3] Move the introduction of commonExitBB until after BuildCFG() so its preds will not have it as succ --- src/mapleall/maple_be/include/cg/cgfunc.h | 1 + .../src/cg/aarch64/aarch64_reg_alloc.cpp | 16 ---------- src/mapleall/maple_be/src/cg/cgfunc.cpp | 31 +++++++------------ 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index 88c4641c3b..f2a1e9b780 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -144,6 +144,7 @@ class CGFunc { void UpdateCallBBFrequency(); void HandleFunction(); void ProcessExitBBVec(); + void AddCommonExitBB(); virtual void MergeReturn() = 0; void TraverseAndClearCatchMark(BB &bb); void MarkCatchBBs(); diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp index a02275ab7a..912c179676 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_reg_alloc.cpp @@ -604,22 +604,6 @@ bool CgRegAlloc::PhaseRun(maplebe::CGFunc &f) { } GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLiveAnalysis::id); } -#if 0 // for exercising postdominance analysis and DoRestorePlacementOpt() - if (f.GetMirModule().GetSrcLang() == kSrcLangC) { - PostDomAnalysis *pdom = nullptr; - MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( - &CgPostDomAnalysis::id, f); - pdom = static_cast(it)->GetResult(); - CHECK_FATAL(pdom != nullptr, "null ptr check"); - MemPool *phaseMp = GetPhaseMemPool(); - MapleAllocator sprealloc(phaseMp); - SPreWorkCand wkCand(&sprealloc); - // initialize the inputs here, e.g. - // wkCand.saveBBs.insert(2); - // wkCand.occBBs.insert(9); - DoRestorePlacementOpt(&f, pdom, &wkCand); - } -#endif GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLoopAnalysis::id); return false; } diff --git a/src/mapleall/maple_be/src/cg/cgfunc.cpp b/src/mapleall/maple_be/src/cg/cgfunc.cpp index a3cf82aa79..c480ba6bb1 100644 --- a/src/mapleall/maple_be/src/cg/cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/cgfunc.cpp @@ -1692,7 +1692,6 @@ void CGFunc::ProcessExitBBVec() { BB *retBB = CreateNewBB(newLabelIdx, cleanupBB->IsUnreachable(), BB::kBBReturn, cleanupBB->GetFrequency()); cleanupBB->PrependBB(*retBB); exitBBVec.emplace_back(retBB); - commonExitBB = retBB; return; } /* split an empty exitBB */ @@ -1716,29 +1715,20 @@ void CGFunc::ProcessExitBBVec() { bb->AddLabel(newLabelIdx); lab2BBMap[newLabelIdx] = bb; } - /* set commonExitBB */ +} + +void CGFunc::AddCommonExitBB() { uint32 i = 0; while (exitBBVec[i]->IsUnreachable() && i < exitBBVec.size()) { i++; } - ASSERT(i < exitBBVec.size(), "all exit BBs are unreacable"); - commonExitBB = exitBBVec[i]; - bool multipleExitBBs = false; - i++; - while (i < exitBBVec.size()) { - if (!exitBBVec[i]->IsUnreachable()) { - multipleExitBBs = true; - break; - } - i++; - } - if (multipleExitBBs) { // create fake commonExitBB - commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0); - ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB"); - for (BB *cgbb : exitBBVec) { - if (!cgbb->IsUnreachable()) { - commonExitBB->PushBackPreds(*cgbb); - } + ASSERT(i < exitBBVec.size(), "all exit BBs are unreachable"); + // create fake commonExitBB + commonExitBB = CreateNewBB(true, BB::kBBFallthru, 0); + ASSERT(commonExitBB != nullptr, "cannot create fake commonExitBB"); + for (BB *cgbb : exitBBVec) { + if (!cgbb->IsUnreachable()) { + commonExitBB->PushBackPreds(*cgbb); } } } @@ -1780,6 +1770,7 @@ void CGFunc::HandleFunction() { /* build control flow graph */ theCFG = memPool->New(*this); theCFG->BuildCFG(); + AddCommonExitBB(); UpdateCallBBFrequency(); if (mirModule.GetSrcLang() != kSrcLangC) { MarkCatchBBs(); -- Gitee