/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MAPLEBE_INCLUDE_CG_LOOP_H #define MAPLEBE_INCLUDE_CG_LOOP_H #include "cg_phase.h" #include "cgbb.h" #include "insn.h" #include "maple_phase.h" namespace maplebe { class LoopHierarchy { public: struct HeadIDCmp { bool operator()(const LoopHierarchy *loopHierarchy1, const LoopHierarchy *loopHierarchy2) const { CHECK_NULL_FATAL(loopHierarchy1); CHECK_NULL_FATAL(loopHierarchy2); return (loopHierarchy1->GetHeader()->GetId() < loopHierarchy2->GetHeader()->GetId()); } }; explicit LoopHierarchy(MemPool &memPool) : loopMemPool(&memPool), otherLoopEntries(loopMemPool.Adapter()), loopMembers(loopMemPool.Adapter()), backedge(loopMemPool.Adapter()), exits(loopMemPool.Adapter()), innerLoops(loopMemPool.Adapter()) { } virtual ~LoopHierarchy() = default; BB *GetHeader() const { return header; } const MapleSet &GetLoopMembers() const { return loopMembers; } const MapleSet &GetBackedge() const { return backedge; } MapleSet &GetBackedgeNonConst() { return backedge; } const MapleSet &GetExits() const { return exits; } const MapleSet &GetInnerLoops() const { return innerLoops; } const LoopHierarchy *GetOuterLoop() const { return outerLoop; } LoopHierarchy *GetPrev() { return prev; } LoopHierarchy *GetNext() { return next; } MapleSet::iterator EraseLoopMembers(MapleSet::iterator it) { return loopMembers.erase(it); } void InsertLoopMembers(BB &bb) { (void)loopMembers.insert(&bb); } void InsertBackedge(BB &bb) { (void)backedge.insert(&bb); } void InsertExit(BB &bb) { (void)exits.insert(&bb); } void InsertInnerLoops(LoopHierarchy &loop) { (void)innerLoops.insert(&loop); } void SetHeader(BB &bb) { header = &bb; } void SetOuterLoop(LoopHierarchy &loop) { outerLoop = &loop; } void SetPrev(LoopHierarchy *loop) { prev = loop; } void SetNext(LoopHierarchy *loop) { next = loop; } void PrintLoops(const std::string &name) const; protected: LoopHierarchy *prev = nullptr; LoopHierarchy *next = nullptr; private: MapleAllocator loopMemPool; BB *header = nullptr; public: MapleSet otherLoopEntries; MapleSet loopMembers; MapleSet backedge; MapleSet exits; MapleSet innerLoops; LoopHierarchy *outerLoop = nullptr; }; class LoopFinder : public AnalysisResult { public: LoopFinder(CGFunc &func, MemPool &mem) : AnalysisResult(&mem), cgFunc(&func), memPool(&mem), loopMemPool(memPool), visitedBBs(loopMemPool.Adapter()), sortedBBs(loopMemPool.Adapter()), dfsBBs(loopMemPool.Adapter()), onPathBBs(loopMemPool.Adapter()), recurseVisited(loopMemPool.Adapter()) { } ~LoopFinder() override = default; void formLoop(BB *headBB, BB *backBB); void seekBackEdge(BB *bb, MapleList succs); void seekCycles(); void markExtraEntryAndEncl(); bool HasSameHeader(const LoopHierarchy *lp1, const LoopHierarchy *lp2); void MergeLoops(); void SortLoops(); void UpdateOuterForInnerLoop(BB *bb, LoopHierarchy *outer); void UpdateOuterLoop(const LoopHierarchy *loop); void CreateInnerLoop(LoopHierarchy &inner, LoopHierarchy &outer); void DetectInnerLoop(); void UpdateCGFunc(); void FormLoopHierarchy(); private: CGFunc *cgFunc; MemPool *memPool; MapleAllocator loopMemPool; MapleVector visitedBBs; MapleVector sortedBBs; MapleStack dfsBBs; MapleVector onPathBBs; MapleVector recurseVisited; LoopHierarchy *loops = nullptr; }; class CGFuncLoops { public: explicit CGFuncLoops(MemPool &memPool) : loopMemPool(&memPool), multiEntries(loopMemPool.Adapter()), loopMembers(loopMemPool.Adapter()), backedge(loopMemPool.Adapter()), exits(loopMemPool.Adapter()), innerLoops(loopMemPool.Adapter()) { } ~CGFuncLoops() = default; void CheckOverlappingInnerLoops(const MapleVector &iLoops, const MapleVector &loopMem) const; void CheckLoops() const; void PrintLoops(const CGFuncLoops &funcLoop) const; const BB *GetHeader() const { return header; } const MapleVector &GetMultiEntries() const { return multiEntries; } const MapleVector &GetLoopMembers() const { return loopMembers; } const MapleVector &GetBackedge() const { return backedge; } const MapleVector &GetExits() const { return exits; } const MapleVector &GetInnerLoops() const { return innerLoops; } const CGFuncLoops *GetOuterLoop() const { return outerLoop; } uint32 GetLoopLevel() const { return loopLevel; } void AddMultiEntries(BB &bb) { multiEntries.emplace_back(&bb); } void AddLoopMembers(BB &bb) { loopMembers.emplace_back(&bb); } void AddBackedge(BB &bb) { backedge.emplace_back(&bb); } void AddExit(BB &bb) { exits.emplace_back(&bb); } void AddInnerLoops(CGFuncLoops &loop) { innerLoops.emplace_back(&loop); } void SetHeader(BB &bb) { header = &bb; } void SetOuterLoop(CGFuncLoops &loop) { outerLoop = &loop; } void SetLoopLevel(uint32 val) { loopLevel = val; } private: MapleAllocator loopMemPool; BB *header = nullptr; MapleVector multiEntries; MapleVector loopMembers; MapleVector backedge; MapleVector exits; MapleVector innerLoops; CGFuncLoops *outerLoop = nullptr; uint32 loopLevel = 0; }; struct CGFuncLoopCmp { bool operator()(const CGFuncLoops *lhs, const CGFuncLoops *rhs) const { CHECK_NULL_FATAL(lhs); CHECK_NULL_FATAL(rhs); return lhs->GetHeader()->GetId() < rhs->GetHeader()->GetId(); } }; MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgLoopAnalysis, maplebe::CGFunc); MAPLE_FUNC_PHASE_DECLARE_END } /* namespace maplebe */ #endif /* MAPLEBE_INCLUDE_CG_LOOP_H */