From 018534ce61e21cf79cb6467508eddc588990f7f5 Mon Sep 17 00:00:00 2001 From: Fred Chow Date: Thu, 3 Feb 2022 21:57:17 -0800 Subject: [PATCH] Implemented cg_ssa_pre.cpp to perform placement optimization for the saves of callee-saved registers. Interface is DoSavePlacementOp(). --- src/mapleall/maple_be/BUILD.gn | 1 + src/mapleall/maple_be/include/cg/cg_ssa_pre.h | 210 +++++++ src/mapleall/maple_be/include/cg/cg_ssu_pre.h | 9 +- src/mapleall/maple_be/src/cg/cg_ssa_pre.cpp | 538 ++++++++++++++++++ 4 files changed, 752 insertions(+), 6 deletions(-) create mode 100644 src/mapleall/maple_be/include/cg/cg_ssa_pre.h create mode 100644 src/mapleall/maple_be/src/cg/cg_ssa_pre.cpp diff --git a/src/mapleall/maple_be/BUILD.gn b/src/mapleall/maple_be/BUILD.gn index 22594cdb66..d26085e392 100644 --- a/src/mapleall/maple_be/BUILD.gn +++ b/src/mapleall/maple_be/BUILD.gn @@ -185,6 +185,7 @@ src_libcg = [ "src/cg/reg_coalesce.cpp", "src/cg/alignment.cpp", "src/cg/cg_ssu_pre.cpp", + "src/cg/cg_ssa_pre.cpp", ] cflags_cc -= [ "-DRC_NO_MMAP" ] diff --git a/src/mapleall/maple_be/include/cg/cg_ssa_pre.h b/src/mapleall/maple_be/include/cg/cg_ssa_pre.h new file mode 100644 index 0000000000..54c308e99e --- /dev/null +++ b/src/mapleall/maple_be/include/cg/cg_ssa_pre.h @@ -0,0 +1,210 @@ +/* + * 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_CG_SSU_PRE_H +#define MAPLEBE_CG_INCLUDE_CG_SSU_PRE_H +#include +#include "mempool.h" +#include "mempool_allocator.h" +#include "cg_dominance.h" + +// Use SSAPRE to determine where to insert saves for callee-saved registers. +// The external interface is DoSavePlacementOpt(). Class SsaPreWorkCand is used +// as input/output interface. + +namespace maplebe { + +typedef uint32 BBId; + +// This must have been constructed by the caller of DoSavePlacementOpt() and +// passed to it as parameter. The caller of DoSavePlacementOpt() describes +// the problem via occBBs. DoSavePlacementOpt()'s outputs are returned to the +// caller by setting saveAtEntryBBs. +class SsaPreWorkCand { + public: + explicit SsaPreWorkCand(MapleAllocator *alloc): + occBBs(alloc->Adapter()), + saveAtEntryBBs(alloc->Adapter()) {} + // inputs + MapleSet occBBs; // Id's of BBs with appearances of the callee-saved reg + // outputs + MapleSet saveAtEntryBBs; // Id's of BBs to insert saves of the register at BB entry + bool saveAtProlog = false; // if true, no shrinkwrapping can be done and + // the other outputs can be ignored +}; + +extern void DoSavePlacementOpt(CGFunc *f, DomAnalysis *dom, SsaPreWorkCand *workCand); + +enum AOccType { + kAOccUndef, + kAOccReal, + kAOccPhi, + kAOccPhiOpnd, + kAOccExit, +}; + +class Occ { + public: + Occ(AOccType ty, BB *bb) : occTy(ty), cgbb(bb) {} + virtual ~Occ() = default; + + virtual void Dump() const = 0; + bool IsDominate(DomAnalysis *dom, const Occ *occ) const { + return dom->Dominate(*cgbb, *occ->cgbb); + } + + AOccType occTy; + uint32 classId = 0; + BB *cgbb; // the BB it occurs in + Occ *def = nullptr; // points to its single def +}; + +class RealOcc : public Occ { + public: + RealOcc(BB *bb): Occ(kAOccReal, bb) {} + virtual ~RealOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "RealOcc at bb" << cgbb->GetId(); + LogInfo::MapleLogger() << " classId" << classId; + } + + bool redundant = true; +}; + +class PhiOcc; + +class PhiOpndOcc : public Occ { + public: + explicit PhiOpndOcc(BB *bb): Occ(kAOccPhiOpnd, bb) {} + virtual ~PhiOpndOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "PhiOpndOcc at bb" << cgbb->GetId() << " classId" << classId; + } + + + PhiOcc *defPhiOcc = nullptr; // its lhs definition + bool hasRealUse = false; + bool insertHere = false; +}; + +class PhiOcc : public Occ { + public: + PhiOcc(BB *bb, MapleAllocator &alloc) + : Occ(kAOccPhi, bb), phiOpnds(alloc.Adapter()) {} + virtual ~PhiOcc() = default; + + bool WillBeAvail() const { + return isCanBeAvail && !isLater; + } + + void Dump() const { + LogInfo::MapleLogger() << "PhiOcc at bb" << cgbb->GetId() << " classId" << classId << " Phi["; + for (size_t i = 0; i < phiOpnds.size(); i++) { + phiOpnds[i]->Dump(); + if (i != phiOpnds.size() - 1) { + LogInfo::MapleLogger() << ", "; + } + } + LogInfo::MapleLogger() << "]"; + } + + + bool isDownsafe = true; + bool isCanBeAvail = true; + bool isLater = true; + MapleVector phiOpnds; +}; + +class ExitOcc : public Occ { + public: + explicit ExitOcc(BB *bb) : Occ(kAOccExit, bb) {} + virtual ~ExitOcc() = default; + + void Dump() const { + LogInfo::MapleLogger() << "ExitOcc at bb" << cgbb->GetId(); + } +}; + +class SSAPre { + public: + SSAPre(CGFunc *cgfunc, DomAnalysis *dm, MemPool *memPool, SsaPreWorkCand *wkcand, bool enDebug) + : cgFunc(cgfunc), + dom(dm), + preMp(memPool), + preAllocator(memPool), + workCand(wkcand), + fullyAntBBs(cgfunc->GetAllBBs().size(), true, preAllocator.Adapter()), + phiDfns(std::less(), preAllocator.Adapter()), + classCount(0), + realOccs(preAllocator.Adapter()), + allOccs(preAllocator.Adapter()), + phiOccs(preAllocator.Adapter()), + exitOccs(preAllocator.Adapter()), + enabledDebug(enDebug) {} + ~SSAPre() = default; + + void ApplySSAPre(); + + private: + // step 6 methods + void CodeMotion(); + // step 5 methods + void Finalize(); + // step 4 methods + void ResetCanBeAvail(PhiOcc *phi) const; + void ComputeCanBeAvail() const; + void ResetLater(PhiOcc *phi) const; + void ComputeLater() const; + // step 3 methods + void ResetDownsafe(const PhiOpndOcc *phiOpnd) const; + void ComputeDownsafe() const; + // step 2 methods + void Rename(); + // step 1 methods + void GetIterDomFrontier(const BB *bb, MapleSet *dfset) const { + for (BBId bbid : dom->GetIdomFrontier(bb->GetId())) { + (void)dfset->insert(dom->GetDtDfnItem(bbid)); + } + } + void FormPhis(); + void CreateSortedOccs(); + // step 0 methods + void PropagateNotAnt(BB *bb, std::set *visitedBBs); + void FormRealsNExits(); + + CGFunc *cgFunc; + DomAnalysis *dom; + MemPool *preMp; + MapleAllocator preAllocator; + SsaPreWorkCand *workCand; + // step 0 + MapleVector fullyAntBBs; // index is BBid; true if occ is fully anticipated at BB entry + // step 1 phi insertion data structures: + MapleSet phiDfns; // set by FormPhis(); set of BBs in terms of their + // dfn's; index into dominance->dt_preorder to get + // their bbid's + // step 2 renaming + uint32 classCount; // for assigning new class id + // the following 4 lists are all maintained in order of dt_preorder + MapleVector realOccs; + MapleVector allOccs; + MapleVector phiOccs; + MapleVector exitOccs; + bool enabledDebug; +}; + +}; // namespace maplabe +#endif // MAPLEBE_CG_INCLUDE_CG_SSA_PRE_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 index 2e9f67c2be..0e47c9fad8 100644 --- a/src/mapleall/maple_be/include/cg/cg_ssu_pre.h +++ b/src/mapleall/maple_be/include/cg/cg_ssu_pre.h @@ -162,7 +162,6 @@ class SSUPre { spreAllocator(memPool), workCand(wkcand), fullyAvailBBs(cgfunc->GetAllBBs().size(), true, spreAllocator.Adapter()), - realOccDfns(std::less(), spreAllocator.Adapter()), lambdaDfns(std::less(), spreAllocator.Adapter()), classCount(0), realOccs(spreAllocator.Adapter()), @@ -198,7 +197,6 @@ class SSUPre { } } void FormLambdas(); - void FormLambdaRes(); void CreateSortedOccs(); // step 0 methods void CreateEntryOcc(BB *bb) { @@ -213,13 +211,12 @@ class SSUPre { 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 MapleVector fullyAvailBBs; // index is BBid; true if occ is fully available at BB exit - MapleSet realOccDfns; // set by FormReals() // step 1 lambda insertion data structures: - MapleSet lambdaDfns; // set by FormLambdas() + MapleSet lambdaDfns; // set by FormLambdas(); set of BBs in terms of + // their dfn's; index into + // dominance->pdt_preorder to get their bbid's // step 2 renaming uint32 classCount; // for assigning new class id // the following 4 lists are all maintained in order of pdt_preorder diff --git a/src/mapleall/maple_be/src/cg/cg_ssa_pre.cpp b/src/mapleall/maple_be/src/cg/cg_ssa_pre.cpp new file mode 100644 index 0000000000..e93a46b1d8 --- /dev/null +++ b/src/mapleall/maple_be/src/cg/cg_ssa_pre.cpp @@ -0,0 +1,538 @@ +/* + * 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_ssa_pre.h" + +namespace maplebe { + +// ================ Step 6: Code Motion ================ +void SSAPre::CodeMotion() { + // pass 1 only doing insertion + for (Occ *occ : allOccs) { + if (occ->occTy != kAOccPhiOpnd) { + continue; + } + PhiOpndOcc *phiOpndOcc = static_cast(occ); + if (phiOpndOcc->insertHere) { + ASSERT(false, "should not do save of callee-save register at BB exit"); + } + } + // pass 2 only doing deletion + for (Occ *occ : realOccs) { + if (occ->occTy != kAOccReal) { + continue; + } + RealOcc *realOcc = static_cast(occ); + if (!realOcc->redundant) { + workCand->saveAtEntryBBs.insert(realOcc->cgbb->GetId()); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ output _______" << '\n'; + LogInfo::MapleLogger() << " saveAtEntryBBs: ["; + for (uint32 id : workCand->saveAtEntryBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n\n"; + } +} + +// ================ Step 5: Finalize ================ +// for setting RealOcc's redundant flag and PhiOpndOcc's insertHere flag +void SSAPre::Finalize() { + std::vector availDefVec(classCount + 1, nullptr); + // preorder traversal of dominator tree + for (Occ *occ : allOccs) { + size_t classId = static_cast(occ->classId); + switch (occ->occTy) { + case kAOccPhi: { + PhiOcc *phiOcc = static_cast(occ); + if (phiOcc->WillBeAvail()) { + availDefVec[classId] = phiOcc; + } + break; + } + case kAOccReal: { + RealOcc *realOcc = static_cast(occ); + if (availDefVec[classId] == nullptr || !availDefVec[classId]->IsDominate(dom, occ)) { + realOcc->redundant = false; + availDefVec[classId] = realOcc; + } else { + realOcc->redundant = true; + } + break; + } + case kAOccPhiOpnd: { + PhiOpndOcc *phiOpndOcc = static_cast(occ); + const PhiOcc *phiOcc = phiOpndOcc->defPhiOcc; + if (phiOcc->WillBeAvail()) { + if (phiOpndOcc->def == nullptr || (!phiOpndOcc->hasRealUse && + phiOpndOcc->def->occTy == kAOccPhi && + !static_cast(phiOpndOcc->def)->WillBeAvail())) { + // insert a store + if (phiOpndOcc->cgbb->GetSuccs().size() != 1) { // critical edge + workCand->saveAtProlog = true; + break; + } + phiOpndOcc->insertHere = true; + } else { + phiOpndOcc->def = availDefVec[classId]; + } + } + break; + } + case kAOccExit: + break; + default: + ASSERT(false, "Finalize: unexpected occ type"); + break; + } + if (workCand->saveAtProlog) { + break; + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after finalize _______" << '\n'; + if (workCand->saveAtProlog) { + LogInfo::MapleLogger() << "Giving up because of insertion at critical edge" << '\n'; + return; + } + for (Occ *occ : allOccs) { + if (occ->occTy == kAOccReal) { + RealOcc *realOcc = static_cast(occ); + if (!realOcc->redundant) { + occ->Dump(); + LogInfo::MapleLogger() << " non-redundant" << '\n'; + } + } else if (occ->occTy == kAOccPhiOpnd) { + PhiOpndOcc *phiOpndOcc = static_cast(occ); + if (phiOpndOcc->insertHere) { + occ->Dump(); + LogInfo::MapleLogger() << " insertHere" << '\n'; + } + } + } + } +} + +// ================ Step 4: WillBeAvail Computation ================ + +void SSAPre::ResetCanBeAvail(PhiOcc *phi) const { + phi->isCanBeAvail = false; + // the following loop finds phi's uses and reset them + for (PhiOcc *phiOcc : phiOccs) { + for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) { + if (phiOpndOcc->def != nullptr && phiOpndOcc->def == phi) { + if (!phiOpndOcc->hasRealUse && !phiOcc->isDownsafe && phiOcc->isCanBeAvail) { + ResetCanBeAvail(phiOcc); + } + } + } + } +} + +void SSAPre::ComputeCanBeAvail() const { + for (PhiOcc *phiOcc : phiOccs) { + if (!phiOcc->isDownsafe && phiOcc->isCanBeAvail) { + bool existNullUse = false; + for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) { + if (phiOpndOcc->def == nullptr) { + existNullUse = true; + break; + } + } + if (existNullUse) { + ResetCanBeAvail(phiOcc); + } + } + } +} + +void SSAPre::ResetLater(PhiOcc *phi) const { + phi->isLater = false; + // the following loop finds phi's uses and reset them + for (PhiOcc *phiOcc : phiOccs) { + for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) { + if (phiOpndOcc->def != nullptr && phiOpndOcc->def == phi) { + if (phiOcc->isLater) { + ResetLater(phiOcc); + } + } + } + } +} + +void SSAPre::ComputeLater() const { + for (PhiOcc *phiOcc : phiOccs) { + phiOcc->isLater = phiOcc->isCanBeAvail; + } + for (PhiOcc *phiOcc : phiOccs) { + if (phiOcc->isLater) { + bool existNonNullUse = false; + for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) { + if (phiOpndOcc->def != nullptr && phiOpndOcc->hasRealUse) { + existNonNullUse = true; + break; + } + } + if (existNonNullUse) { + ResetLater(phiOcc); + } + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after later computation _______" << '\n'; + for (PhiOcc *phiOcc : phiOccs) { + phiOcc->Dump(); + if (phiOcc->isCanBeAvail) { + LogInfo::MapleLogger() << " canbeAvail"; + } + if (phiOcc->isLater) { + LogInfo::MapleLogger() << " later"; + } + if (phiOcc->isCanBeAvail && !phiOcc->isLater) { + LogInfo::MapleLogger() << " will be Avail"; + } + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 3: Downsafe Computation ================ +void SSAPre::ResetDownsafe(const PhiOpndOcc *phiOpnd) const { + if (phiOpnd->hasRealUse) { + return; + } + Occ *defOcc = phiOpnd->def; + if (defOcc == nullptr || defOcc->occTy != kAOccPhi) { + return; + } + PhiOcc *defPhiOcc = static_cast(defOcc); + if (!defPhiOcc->isDownsafe) { + return; + } + defPhiOcc->isDownsafe = false; + for (PhiOpndOcc *phiOpndOcc : defPhiOcc->phiOpnds) { + ResetDownsafe(phiOpndOcc); + } +} + +void SSAPre::ComputeDownsafe() const { + for (PhiOcc *phiOcc : phiOccs) { + if (!phiOcc->isDownsafe) { + // propagate not-Downsafe backward along use-def edges + for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) { + ResetDownsafe(phiOpndOcc); + } + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after downsafe computation _______" << '\n'; + for (PhiOcc *phiOcc : phiOccs) { + phiOcc->Dump(); + if (phiOcc->isDownsafe) { + LogInfo::MapleLogger() << " downsafe"; + } + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 2: rename ================ +void SSAPre::Rename() { + std::stack occStack; + classCount = 0; + // iterate thru the occurrences in order of preorder traversal of dominator + // tree + for (Occ *occ : allOccs) { + while (!occStack.empty() && !occStack.top()->IsDominate(dom, occ)) { + occStack.pop(); + } + switch (occ->occTy) { + case kAOccExit: + if (!occStack.empty()) { + Occ *topOcc = occStack.top(); + if (topOcc->occTy == kAOccPhi) { + static_cast(topOcc)->isDownsafe = false; + } + } + break; + case kAOccPhi: + // assign new class + occ->classId = ++classCount; + occStack.push(occ); + break; + case kAOccReal: { + if (occStack.empty()) { + // assign new class + occ->classId = ++classCount; + occStack.push(occ); + break; + } + Occ *topOcc = occStack.top(); + occ->classId = topOcc->classId; + if (topOcc->occTy == kAOccPhi) { + occStack.push(occ); + } + break; + } + case kAOccPhiOpnd: { + if (occStack.empty()) { + // leave classId as 0 + break; + } + Occ *topOcc = occStack.top(); + occ->def = topOcc; + occ->classId = topOcc->classId; + if (topOcc->occTy == kAOccReal) { + static_cast(occ)->hasRealUse = true; + } + break; + } + default: + ASSERT(false, "Rename: unexpected type of occurrence"); + break; + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after rename _______" << '\n'; + for (Occ *occ : allOccs) { + occ->Dump(); + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 1: insert phis ================ + +// form pih occ based on the real occ in workCand->realOccs; result is +// stored in phiDfns +void SSAPre::FormPhis() { + for (Occ *occ : realOccs) { + GetIterDomFrontier(occ->cgbb, &phiDfns); + } +} + +// form allOccs inclusive of real, phi, phiOpnd, exit occurrences; +// form phiOccs containing only the phis +void SSAPre::CreateSortedOccs() { + // form phiOpnd occs based on the preds of the phi occs; result is + // stored in phiOpndDfns + std::multiset phiOpndDfns; + for (uint32 dfn : phiDfns) { + const BBId bbId = dom->GetDtPreOrderItem(dfn); + BB *cgbb = cgFunc->GetAllBBs()[bbId]; + for (BB *pred : cgbb->GetPreds()) { + (void)phiOpndDfns.insert(dom->GetDtDfnItem(pred->GetId())); + } + } + std::unordered_map> bb2PhiOpndMap; + MapleVector::iterator realOccIt = realOccs.begin(); + MapleVector::iterator exitOccIt = exitOccs.begin(); + MapleSet::iterator phiDfnIt = phiDfns.begin(); + MapleSet::iterator phiOpndDfnIt = phiOpndDfns.begin(); + Occ *nextRealOcc = nullptr; + if (realOccIt != realOccs.end()) { + nextRealOcc = *realOccIt; + } + ExitOcc *nextExitOcc = nullptr; + if (exitOccIt != exitOccs.end()) { + nextExitOcc = *exitOccIt; + } + PhiOcc *nextPhiOcc = nullptr; + if (phiDfnIt != phiDfns.end()) { + nextPhiOcc = preMp->New(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiDfnIt)), preAllocator); + } + PhiOpndOcc *nextPhiOpndOcc = nullptr; + if (phiOpndDfnIt != phiOpndDfns.end()) { + nextPhiOpndOcc = preMp->New(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiOpndDfnIt))); + auto it = bb2PhiOpndMap.find(dom->GetDtPreOrderItem(*phiOpndDfnIt)); + if (it == bb2PhiOpndMap.end()) { + std::forward_list newlist = { nextPhiOpndOcc }; + bb2PhiOpndMap[dom->GetDtPreOrderItem(*phiOpndDfnIt)] = newlist; + } else { + it->second.push_front(nextPhiOpndOcc); + } + } + Occ *pickedOcc = nullptr; // the next picked occ in order of preorder traversal of dominator tree + do { + pickedOcc = nullptr; + if (nextPhiOcc != nullptr) { + pickedOcc = nextPhiOcc; + } + if (nextRealOcc != nullptr && (pickedOcc == nullptr || dom->GetDtDfnItem(nextRealOcc->cgbb->GetId()) < + dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextRealOcc; + } + if (nextPhiOpndOcc != nullptr && + (pickedOcc == nullptr || *phiOpndDfnIt < dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextPhiOpndOcc; + } + if (nextExitOcc != nullptr && (pickedOcc == nullptr || dom->GetDtDfnItem(nextExitOcc->cgbb->GetId()) < + dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) { + pickedOcc = nextExitOcc; + } + if (pickedOcc != nullptr) { + allOccs.push_back(pickedOcc); + switch (pickedOcc->occTy) { + case kAOccReal: { + // get the next real occ + CHECK_FATAL(realOccIt != realOccs.end(), "iterator check"); + ++realOccIt; + if (realOccIt != realOccs.end()) { + nextRealOcc = *realOccIt; + } else { + nextRealOcc = nullptr; + } + break; + } + case kAOccExit: { + CHECK_FATAL(exitOccIt != exitOccs.end(), "iterator check"); + ++exitOccIt; + if (exitOccIt != exitOccs.end()) { + nextExitOcc = *exitOccIt; + } else { + nextExitOcc = nullptr; + } + break; + } + case kAOccPhi: { + phiOccs.push_back(static_cast(pickedOcc)); + CHECK_FATAL(phiDfnIt != phiDfns.end(), "iterator check"); + ++phiDfnIt; + if (phiDfnIt != phiDfns.end()) { + nextPhiOcc = preMp->New(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiDfnIt)), preAllocator); + } else { + nextPhiOcc = nullptr; + } + break; + } + case kAOccPhiOpnd: { + CHECK_FATAL(phiOpndDfnIt != phiOpndDfns.end(), "iterator check"); + ++phiOpndDfnIt; + if (phiOpndDfnIt != phiOpndDfns.end()) { + nextPhiOpndOcc = preMp->New(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiOpndDfnIt))); + auto it = bb2PhiOpndMap.find(dom->GetDtPreOrderItem(*phiOpndDfnIt)); + if (it == bb2PhiOpndMap.end()) { + std::forward_list newlist = { nextPhiOpndOcc }; + bb2PhiOpndMap[dom->GetDtPreOrderItem(*phiOpndDfnIt)] = newlist; + } else { + it->second.push_front(nextPhiOpndOcc); + } + } else { + nextPhiOpndOcc = nullptr; + } + break; + } + default: + ASSERT(false, "CreateSortedOccs: unexpected occTy"); + break; + } + } + } while (pickedOcc != nullptr); + // initialize phiOpnd vector in each PhiOcc node and defPhiOcc in each PhiOpndOcc + for (PhiOcc *phiOcc : phiOccs) { + for (BB *pred : phiOcc->cgbb->GetPreds()) { + PhiOpndOcc *phiOpndOcc = bb2PhiOpndMap[pred->GetId()].front(); + phiOcc->phiOpnds.push_back(phiOpndOcc); + phiOpndOcc->defPhiOcc = phiOcc; + bb2PhiOpndMap[pred->GetId()].pop_front(); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << " _______ after phi insertion _______" << '\n'; + for (Occ *occ : allOccs) { + occ->Dump(); + LogInfo::MapleLogger() << '\n'; + } + } +} + +// ================ Step 0: Preparations ================ + +void SSAPre::PropagateNotAnt(BB *bb, std::set *visitedBBs) { + if (visitedBBs->count(bb) != 0) { + return; + } + visitedBBs->insert(bb); + if (workCand->occBBs.count(bb->GetId()) != 0) { + return; + } + fullyAntBBs[bb->GetId()] = false; + for (BB *predbb : bb->GetPreds()) { + PropagateNotAnt(predbb, visitedBBs); + } +} + +void SSAPre::FormRealsNExits() { + std::set visitedBBs; + PropagateNotAnt(cgFunc->GetCommonExitBB(), &visitedBBs); + + for (uint32 i = 0; i < dom->GetDtPreOrderSize(); i++) { + BBId bbid = dom->GetDtPreOrderItem(i); + BB *cgbb = cgFunc->GetAllBBs()[bbid]; + if (fullyAntBBs[cgbb->GetId()]) { + RealOcc *realOcc = preMp->New(cgbb); + realOccs.push_back(realOcc); + } + if (!cgbb->IsUnreachable() && (cgbb->NumSuccs() == 0 || cgbb->GetKind() == BB::kBBReturn)) { + ExitOcc *exitOcc = preMp->New(cgbb); + exitOccs.push_back(exitOcc); + } + } + if (enabledDebug) { + LogInfo::MapleLogger() << "Placement Optimization for callee-save saves" << '\n'; + LogInfo::MapleLogger() << "-----------------------------------------------" << '\n'; + LogInfo::MapleLogger() << " _______ input _______" << '\n'; + LogInfo::MapleLogger() << " occBBs: ["; + for (uint32 id : workCand->occBBs) { + LogInfo::MapleLogger() << id << " "; + } + LogInfo::MapleLogger() << "]\n"; + } +} + +void SSAPre::ApplySSAPre() { + FormRealsNExits(); + // #1 insert phis; results in allOccs and phiOccs + FormPhis(); // result put in the set phi_bbs + CreateSortedOccs(); + // #2 rename + Rename(); + if (!phiOccs.empty()) { + // #3 DownSafety + ComputeDownsafe(); + // #4 CanBeAvail + ComputeCanBeAvail(); + ComputeLater(); + } + // #5 Finalize + Finalize(); + if (!workCand->saveAtProlog) { + // #6 Code Motion + CodeMotion(); + } +} + +void DoSavePlacementOpt(CGFunc *f, DomAnalysis *dom, SsaPreWorkCand *workCand) { + MemPool *tempMP = memPoolCtrler.NewMemPool("cg_ssa_pre", true); + SSAPre cgssapre(f, dom, tempMP, workCand, false/*enabledDebug*/); + + cgssapre.ApplySSAPre(); + + memPoolCtrler.DeleteMemPool(tempMP); +} + +} // namespace maplebe -- Gitee