From 713c78764a79e8fd777de7d5df19311bbc4688ef Mon Sep 17 00:00:00 2001 From: Alfred Huang Date: Sat, 6 Aug 2022 16:16:53 -0700 Subject: [PATCH 1/2] Enhanced and default --calleeregs-placement to ssapre-save. --- .../include/cg/aarch64/aarch64_regsaves.h | 76 +++- .../src/cg/aarch64/aarch64_regsaves.cpp | 332 ++++++++++++++---- src/mapleall/maple_be/src/cg/cg_option.cpp | 2 +- 3 files changed, 324 insertions(+), 86 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h index 26a00f61c6..d7f2eb318d 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h @@ -24,8 +24,9 @@ namespace maplebe { -/* Saved reg info. This class is created to avoid the complexity of - nested Maple Containers */ +#define BBid uint32 + +/* Saved callee-save reg info */ class SavedRegInfo { public: bool insertAtLastMinusOne = false; @@ -89,6 +90,7 @@ class SavedRegInfo { MapleSet restoreExitSet; }; +/* BBs info for saved callee-saved reg */ class SavedBBInfo { public: explicit SavedBBInfo(MapleAllocator &alloc) : bbList (alloc.Adapter()) {} @@ -109,6 +111,27 @@ class SavedBBInfo { MapleSet bbList; }; +/* Info for BBs reachable from current BB */ +class ReachInfo { + public: + explicit ReachInfo(MapleAllocator &alloc) : bbList (alloc.Adapter()) {} + + MapleSet &GetBBList() { + return bbList; + } + + bool ContainInReachingBBs(BBid bid) { + if (bbList.find(bid) != bbList.end()) { + return true; + } + return false; + } + + private: + MapleSet bbList; +}; + + class AArch64RegSavesOpt : public RegSavesOpt { public: AArch64RegSavesOpt(CGFunc &func, MemPool &pool, DomAnalysis &dom, PostDomAnalysis &pdom) @@ -117,7 +140,9 @@ class AArch64RegSavesOpt : public RegSavesOpt { pDomInfo(&pdom), bbSavedRegs(alloc.Adapter()), regSavedBBs(alloc.Adapter()), + reachingBBs(alloc.Adapter()), regOffset(alloc.Adapter()), + visited(alloc.Adapter()), id2bb(alloc.Adapter()) { bbSavedRegs.resize(func.NumBBs()); regSavedBBs.resize(sizeof(CalleeBitsType)<<3); @@ -127,6 +152,10 @@ class AArch64RegSavesOpt : public RegSavesOpt { for (size_t i = 0; i < regSavedBBs.size(); ++i) { regSavedBBs[i] = nullptr; } + reachingBBs.resize(func.NumBBs()); + for (size_t i = 0; i < bbSavedRegs.size(); ++i) { + reachingBBs[i] = nullptr; + } } ~AArch64RegSavesOpt() override = default; @@ -140,16 +169,21 @@ class AArch64RegSavesOpt : public RegSavesOpt { void ProcessListOpnd(const BB &bb, Operand &opnd); void ProcessMemOpnd(const BB &bb, Operand &opnd); void ProcessCondOpnd(const BB &bb); - void GetLocalDefUse(); + void GenAccDefs(); + void GenRegDefUse(); + bool CheckForUseBeforeDefPath(); void PrintBBs() const; int CheckCriteria(BB *bb, regno_t reg) const; bool AlreadySavedInDominatorList(const BB *bb, regno_t reg) const; void DetermineCalleeSaveLocationsDoms(); void DetermineCalleeSaveLocationsPre(); bool DetermineCalleeRestoreLocations(); - int32 FindNextOffsetForCalleeSave() const; + int32 FindCalleeBase() const; + void AdjustRegOffsets(); void InsertCalleeSaveCode(); void InsertCalleeRestoreCode(); + void CreateReachingBBs(ReachInfo *rp, BB *bb); + BB* RemoveRedundancy(BB *startbb, regno_t reg); void Verify(regno_t reg, BB* bb, std::set *visited, uint32 *s, uint32 *r); void Run() override; @@ -173,23 +207,31 @@ class AArch64RegSavesOpt : public RegSavesOpt { return calleeBitsUse; } - CalleeBitsType GetBBCalleeBits(CalleeBitsType *data, uint32 bid) const { + CalleeBitsType *GetCalleeBitsAcc() { + return calleeBitsAcc; + } + + CalleeBitsType GetBBCalleeBits(CalleeBitsType *data, BBid bid) const { return data[bid]; } - void SetCalleeBit(CalleeBitsType *data, uint32 bid, regno_t reg) const { + void SetCalleeBit(CalleeBitsType *dest, BBid bidD, CalleeBitsType src) { + dest[bidD] = src; + } + + void SetCalleeBit(CalleeBitsType *data, BBid bid, regno_t reg) { CalleeBitsType mask = 1ULL << RegBitMap(reg); if ((GetBBCalleeBits(data, bid) & mask) == 0) { data[bid] = GetBBCalleeBits(data, bid) | mask; } } - void ResetCalleeBit(CalleeBitsType * data, uint32 bid, regno_t reg) const { + void ResetCalleeBit(CalleeBitsType * data, BBid bid, regno_t reg) { CalleeBitsType mask = 1ULL << RegBitMap(reg); data[bid] = GetBBCalleeBits(data, bid) & ~mask; } - bool IsCalleeBitSet(CalleeBitsType * data, uint32 bid, regno_t reg) const { + bool IsCalleeBitSet(CalleeBitsType * data, BBid bid, regno_t reg) const { CalleeBitsType mask = 1ULL << RegBitMap(reg); return GetBBCalleeBits(data, bid) & mask; } @@ -215,18 +257,25 @@ class AArch64RegSavesOpt : public RegSavesOpt { } } - SavedRegInfo *GetbbSavedRegsEntry(uint32 bid) { + SavedRegInfo *GetbbSavedRegsEntry(BBid bid) { if (bbSavedRegs[bid] == nullptr) { bbSavedRegs[bid] = memPool->New(alloc); } return bbSavedRegs[bid]; } + ReachInfo *GetReachingEntry(BBid bid) { + if (reachingBBs[bid] == nullptr) { + reachingBBs[bid] = memPool->New(alloc); + } + return reachingBBs[bid]; + } + void SetId2bb(BB *bb) { id2bb[bb->GetId()] = bb; } - BB *GetId2bb(uint32 bid) { + BB *GetId2bb(BBid bid) { return id2bb[bid]; } @@ -236,12 +285,13 @@ class AArch64RegSavesOpt : public RegSavesOpt { Bfs *bfs = nullptr; CalleeBitsType *calleeBitsDef = nullptr; CalleeBitsType *calleeBitsUse = nullptr; + CalleeBitsType *calleeBitsAcc = nullptr; MapleVector bbSavedRegs; /* set of regs to be saved in a BB */ MapleVector regSavedBBs; /* set of BBs to be saved for a reg */ + MapleVector reachingBBs; /* set of BBs reachable from a BB */ MapleMap regOffset; /* save offset of each register */ - MapleMap id2bb; /* bbid to bb* mapping */ - bool oneAtaTime = false; - regno_t oneAtaTimeReg = 0; + MapleSet visited; /* temp */ + MapleMap id2bb; /* bbid to bb* mapping */ }; } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp index e9ebf4b223..d06adf49ea 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp @@ -26,8 +26,21 @@ namespace maplebe { #define RS_DUMP GetEnabledDebug() #define RS_EXTRA (RS_DUMP && true) #define M_LOG LogInfo::MapleLogger() -#define THRESHOLD 8 -#define ONE_REG_AT_A_TIME 0 + +#define SKIP_FPLR(REG) \ + if (REG >= R29 && REG < V8) { \ + continue; \ + } + +void AArch64RegSavesOpt::CreateReachingBBs(ReachInfo *rp, BB *bb) { + (void)visited.insert(bb->GetId()); + rp->GetBBList().insert(bb->GetId()); + for (auto succ : bb->GetSuccs()) { + if (visited.count(succ->GetId()) == 0) { + CreateReachingBBs(rp, succ); + } + } +} void AArch64RegSavesOpt::InitData() { calleeBitsDef = cgFunc->GetMemoryPool()->NewArray(cgFunc->NumBBs()); @@ -36,7 +49,10 @@ void AArch64RegSavesOpt::InitData() { calleeBitsUse = cgFunc->GetMemoryPool()->NewArray(cgFunc->NumBBs()); errno_t retUse = memset_s(calleeBitsUse, cgFunc->NumBBs() * sizeof(CalleeBitsType), 0, cgFunc->NumBBs() * sizeof(CalleeBitsType)); - CHECK_FATAL(retDef == EOK && retUse == EOK, "memset_s of calleesBits failed"); + calleeBitsAcc = cgFunc->GetMemoryPool()->NewArray(cgFunc->NumBBs()); + errno_t retAccDef = memset_s(calleeBitsAcc, cgFunc->NumBBs() * sizeof(CalleeBitsType), + 0, cgFunc->NumBBs() * sizeof(CalleeBitsType)); + CHECK_FATAL(retDef == EOK && retUse == EOK && retAccDef == EOK, "memset_s of calleesBits failed"); AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); const MapleVector &sp = aarchCGFunc->GetCalleeSavedRegs(); @@ -141,9 +157,43 @@ void AArch64RegSavesOpt::ProcessCondOpnd(const BB &bb) { CollectLiveInfo(bb, rflag, false, true); } +void AArch64RegSavesOpt::GenAccDefs() { + /* Set up accumulated callee def bits in all blocks */ + for (auto bb : bfs->sortedBBs) { + if (bb->GetPreds().size() == 0) { + SetCalleeBit(GetCalleeBitsAcc(), bb->GetId(), GetBBCalleeBits(GetCalleeBitsDef(), bb->GetId())); + } else { + CalleeBitsType curbbBits = GetBBCalleeBits(GetCalleeBitsDef(), bb->GetId()); + int64 n = -1; + CalleeBitsType tmp = (CalleeBitsType)n; + CGFuncLoops *loop = bb->GetLoop(); + for (auto pred : bb->GetPreds()) { + if (loop != nullptr && loop->GetHeader() == bb) { + if (find(loop->GetBackedge().begin(), loop->GetBackedge().end(), pred) != loop->GetBackedge().end()) { + continue; + } + } + if (pred->GetKind() == BB::kBBGoto) { + if (pred->NumInsn() > 1) { + Insn *insn = pred->GetLastInsn()->GetPrev(); + if (insn->GetMachineOpcode() == MOP_xbl) { + auto *nameOpnd = static_cast(&insn->GetOperand(kInsnFirstOpnd)); + if (nameOpnd->GetName() == "fancy_abort") { + continue; /* skip unreachable */ + } + } + } + } + tmp &= GetBBCalleeBits(GetCalleeBitsAcc(), pred->GetId()); + } + SetCalleeBit(GetCalleeBitsAcc(), bb->GetId(), curbbBits | tmp ); + } + } +} + /* Record in each local BB the 1st def and the last use of a callee-saved register */ -void AArch64RegSavesOpt::GetLocalDefUse() { +void AArch64RegSavesOpt::GenRegDefUse() { for (auto bbp : bfs->sortedBBs) { BB &bb = *bbp; if (bb.GetKind() == BB::kBBReturn) { @@ -183,24 +233,50 @@ void AArch64RegSavesOpt::GetLocalDefUse() { } /* for all insns */ } /* for all sortedBBs */ + GenAccDefs(); + if (RS_DUMP) { - for (uint32 i = 0; i < cgFunc->NumBBs(); ++i) { - M_LOG << i << " : " << calleeBitsDef[i] << " " << calleeBitsUse[i] << "\n"; + M_LOG << "CalleeBits for " << cgFunc->GetName() << ":\n"; + for (BBid i = 1; i < cgFunc->NumBBs(); ++i) { + M_LOG << i << " : " << calleeBitsDef[i] << " " << calleeBitsUse[i] << " " << calleeBitsAcc[i] << "\n"; } } } +bool AArch64RegSavesOpt::CheckForUseBeforeDefPath() { + /* Check if any block has a use without a def as shown in its accumulated + calleeBitsDef from above */ + for (BBid bid = 0; bid < cgFunc->NumBBs(); ++bid) { + CalleeBitsType use = GetBBCalleeBits(GetCalleeBitsUse(), bid); + CalleeBitsType acc = GetBBCalleeBits(GetCalleeBitsAcc(), bid); + if ((use & acc) != use) { + if (RS_DUMP) { + CalleeBitsType mask = 1; + for (uint32 i = 0; i < static_cast(sizeof(CalleeBitsType) << 3); ++i) { + regno_t reg = ReverseRegBitMap(i); + if ((use & mask) != 0 && (acc & mask) == 0) { + M_LOG << "R" << reg - 1 << " in BB" << bid << " is in a use before def path\n"; + } + mask <<= 1; + } + } + return true; + } + } + return false; +} + void AArch64RegSavesOpt::PrintBBs() const { M_LOG << "RegSaves LiveIn/Out of BFS nodes:\n"; for (auto *bb : bfs->sortedBBs) { M_LOG << "< === > "; M_LOG << bb->GetId(); M_LOG << " pred:["; - for (auto *predBB : bb->GetPreds()) { + for (auto predBB : bb->GetPreds()) { M_LOG << " " << predBB->GetId(); } M_LOG << "] succs:["; - for (auto *succBB : bb->GetSuccs()) { + for (auto succBB : bb->GetSuccs()) { M_LOG << " " << succBB->GetId(); } M_LOG << "]\n LiveIn of [" << bb->GetId() << "]: "; @@ -262,6 +338,77 @@ bool AArch64RegSavesOpt::AlreadySavedInDominatorList(const BB *bb, regno_t reg) return false; /* not previously saved, to save at bb */ } +#if REMOVE_DOM_REDUNDANCY +/* Return true if reg is already to be saved in all paths to target + from already saved BBs */ +BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { + uint32 cbit = RegBitMap(reg); + if (regSavedBBs[cbit] == nullptr) { + return target; /* no previously save */ + } + MapleSet &saveSet = regSavedBBs[cbit]->GetBBList(); + BB *targ = target; + while (true) { + if (targ->GetPreds().empty()) { + break; /* entry node */ + } + BBid tbid = targ->GetId(); + bool change = false; + for (BB *from : saveSet) { + BBid fbid = from->GetId(); + if (tbid == fbid) { + continue; + } + ReachInfo *rp = GetReachingEntry(fbid); + if (rp->GetBBList().empty()) { + (void)visited.clear(); + CreateReachingBBs(rp, from); + if (RS_DUMP) { + M_LOG << " --ReachingBBs for BB " << from->GetId() << " created\n"; + } + } + if (rp->ContainInReachingBBs(tbid)) { /* BB reaches curbb */ + change = true; + targ = GetDomInfo()->GetDom(tbid); + break; + } + } + if (!change) { + break; /* targ is dest */ + } + } + + /* If the newly found blk reaches any already previously saved blocks, + remove these blks from bbSavedRegs */ + ReachInfo *rp = GetReachingEntry(targ->GetId()); + if (rp->GetBBList().empty()) { + if (RS_DUMP) { + M_LOG << " --ReachingBBs for BB " << targ->GetId() << " created\n"; + } + CreateReachingBBs(rp, targ); + } + for (BB *bb : saveSet) { + if (bb->GetId() == targ->GetId()) { + if (RS_DUMP) { + M_LOG << " --R" << reg - 1 << " already saved in BB" << targ->GetId()<< "\n"; + } + continue; + } else if (bb->GetPreds().empty()) { + continue; + } + if (rp->ContainInReachingBBs(bb->GetId())) { + saveSet.erase(bb); + bbSavedRegs[bb->GetId()]->RemoveSaveReg(reg); + if (RS_DUMP) { + M_LOG << " --R" << (reg - 1) << " save removed from BB" << bb->GetId() << "\n"; + } + } + } + + return targ; +} +#endif + /* Determine callee-save regs save locations and record them in bbSavedRegs. Save is needed for a 1st def callee-save register at its dominator block outside any loop. */ @@ -282,10 +429,6 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsDoms() { if ((c & mask) != 0) { MapleSet &liveIn = bb->GetLiveInRegNO(); regno_t reg = ReverseRegBitMap(i); - if (oneAtaTime && oneAtaTimeReg != reg) { - mask <<= 1; - continue; - } if (liveIn.find(reg) == liveIn.end()) { /* not livein */ BB *bbDom = bb; /* start from current BB */ bool done = false; @@ -302,14 +445,22 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsDoms() { continue; } +#if REMOVE_DOM_REDUNDANCY + bbDom = RemoveRedundancy(bbDom, reg); + if (regSavedBBs[i] == nullptr) { + regSavedBBs[i] = memPool->New(alloc); + } + regSavedBBs[i]->InsertBB(bbDom); +#endif + /* Check if a dominator of bbDom was already a location to save */ if (AlreadySavedInDominatorList(bbDom, reg)) { mask <<= 1; continue; /* no need to save again, next reg */ } - /* Check if the newly found block is a dominator of block(s) in the current - to be saved list. If so, remove these blocks from bbSavedRegs */ + /* If the newly found blk is a dominator of blk(s) in the current + to be saved list, remove these blks from bbSavedRegs */ uint32 creg = i; SavedBBInfo *sp = regSavedBBs[creg]; if (sp == nullptr) { @@ -332,7 +483,7 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsDoms() { } regSavedBBs[creg]->InsertBB(bbDom); - uint32 bid = bbDom->GetId(); + BBid bid = bbDom->GetId(); if (RS_DUMP) { M_LOG << " --R" << (reg - 1); M_LOG << " to save in " << bid << "\n"; @@ -360,21 +511,38 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsPre() { M_LOG << "Determining regsave sites using ssa_pre for " << cgFunc->GetName() << ":\n"; } const MapleVector &callees = aarchCGFunc->GetCalleeSavedRegs(); + int32 offset = FindCalleeBase(); for (auto reg : callees) { - if (reg >= R29 && reg < V8) { - continue; /* save/restore in prologue, epilogue */ + SKIP_FPLR(reg); + if (regOffset.find(reg) == regOffset.end()) { + regOffset[reg] = static_cast(offset); + offset += static_cast(kIntregBytelen); } - if (oneAtaTime && oneAtaTimeReg != reg) { - continue; + } + /* do 2 regs at a time to force store pairs */ + for (int i = 0; i < callees.size(); i++) { + AArch64reg reg1 = callees[i]; + SKIP_FPLR(reg1); + AArch64reg reg2 = kRinvalid; + if ((i+1) < callees.size()) { + reg2 = callees[i+1]; + SKIP_FPLR(reg2); + i++; } SsaPreWorkCand wkCand(&sprealloc); - for (uint32 bid = 1; bid < static_cast(bbSavedRegs.size()); ++bid) { + for (BBid bid = 1; bid < static_cast(bbSavedRegs.size()); ++bid) { /* Set the BB occurrences of this callee-saved register */ - if (IsCalleeBitSet(GetCalleeBitsDef(), bid, reg) || - IsCalleeBitSet(GetCalleeBitsUse(), bid, reg)) { + if (IsCalleeBitSet(GetCalleeBitsDef(), bid, reg1) || + IsCalleeBitSet(GetCalleeBitsUse(), bid, reg1)) { (void)wkCand.occBBs.insert(bid); } + if (reg2 != kRinvalid) { + if (IsCalleeBitSet(GetCalleeBitsDef(), bid, reg2) || + IsCalleeBitSet(GetCalleeBitsUse(), bid, reg2)) { + (void)wkCand.occBBs.insert(bid); + } + } } DoSavePlacementOpt(cgFunc, GetDomInfo(), &wkCand); if (wkCand.saveAtEntryBBs.empty()) { @@ -385,21 +553,34 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsPre() { /* Save cannot be applied, skip this reg and place save/restore in prolog/epilog */ MapleVector &pe = aarchCGFunc->GetProEpilogSavedRegs(); - if (std::find(pe.begin(), pe.end(), reg) == pe.end()) { - pe.push_back(reg); + if (std::find(pe.begin(), pe.end(), reg1) == pe.end()) { + pe.push_back(reg1); + } + if (reg2 != kRinvalid && std::find(pe.begin(), pe.end(), reg2) == pe.end()) { + pe.push_back(reg2); } if (RS_DUMP) { - M_LOG << "Save R" << (reg - 1) << " n/a, do in Pro/Epilog\n"; + M_LOG << "Save R" << (reg1 - 1) << " n/a, do in Pro/Epilog\n"; + if (reg2 != kRinvalid) { + M_LOG << " R " << (reg2 - 1) << " n/a, do in Pro/Epilog\n"; + } } continue; } if (!wkCand.saveAtEntryBBs.empty()) { - for (uint32 entBB : wkCand.saveAtEntryBBs) { + for (BBid entBB : wkCand.saveAtEntryBBs) { if (RS_DUMP) { - std::string r = reg <= R28 ? "r" : "v"; - M_LOG << "BB " << entBB << " save: " << r << (reg - 1) << "\n"; + std::string r = reg1 <= R28 ? "R" : "V"; + M_LOG << "BB " << entBB << " save for : " << r << (reg1 - 1) << "\n"; + if (reg2 != kRinvalid) { + std::string r = reg2 <= R28 ? "R" : "V"; + M_LOG << " : " << r << (reg2 - 1) << "\n"; + } + } + GetbbSavedRegsEntry(entBB)->InsertSaveReg(reg1); + if (reg2 != kRinvalid) { + GetbbSavedRegsEntry(entBB)->InsertSaveReg(reg2); } - GetbbSavedRegsEntry(entBB)->InsertSaveReg(reg); } } } @@ -415,19 +596,10 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { } const MapleVector &callees = aarchCGFunc->GetCalleeSavedRegs(); for (auto reg : callees) { - if (reg >= R29 && reg < V8) { - continue; /* save/restore in prologue, epilogue */ - } - if (oneAtaTime && oneAtaTimeReg != reg) { - MapleVector &pe = aarchCGFunc->GetProEpilogSavedRegs(); - if (std::find(pe.begin(), pe.end(), reg) == pe.end()) { - pe.push_back(reg); - } - continue; - } + SKIP_FPLR(reg); SPreWorkCand wkCand(&sprealloc); - for (uint32 bid = 1; bid < static_cast(bbSavedRegs.size()); ++bid) { + for (BBid bid = 1; bid < static_cast(bbSavedRegs.size()); ++bid) { /* Set the saved BB locations of this callee-saved register */ SavedRegInfo *sp = bbSavedRegs[bid]; if (sp != nullptr) { @@ -446,14 +618,19 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { /* something gone wrong, skip this reg */ wkCand.restoreAtEpilog = true; } - /* splitted empty block for critical edge present, skip function */ - MapleSet rset = wkCand.restoreAtEntryBBs; + /* splitted empty block for critical edge present, skip reg */ + MapleSet rset = wkCand.restoreAtEntryBBs; for (auto bbid : wkCand.restoreAtExitBBs) { (void)rset.insert(bbid); } for (auto bbid : rset) { BB *bb = GetId2bb(bbid); if (bb->GetKind() == BB::kBBGoto && bb->NumInsn() == 1) { + if (RS_DUMP) { + M_LOG << "Restores in splitted empty BB" << bbid << "\n"; + } + // wkCand.restoreAtEpilog = true; + // break; aarchCGFunc->GetProEpilogSavedRegs().clear(); const MapleVector &calleesNew = aarchCGFunc->GetCalleeSavedRegs(); for (auto areg : calleesNew) { @@ -463,7 +640,7 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { } } if (wkCand.restoreAtEpilog) { - /* Restore cannot b3 applied, skip this reg and place save/restore + /* Restore cannot be applied, skip this reg and place save/restore in prolog/epilog */ for (size_t bid = 1; bid < bbSavedRegs.size(); ++bid) { SavedRegInfo *sp = bbSavedRegs[bid]; @@ -483,14 +660,14 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { continue; } if (!wkCand.restoreAtEntryBBs.empty() || !wkCand.restoreAtExitBBs.empty()) { - for (uint32 entBB : wkCand.restoreAtEntryBBs) { + for (BBid entBB : wkCand.restoreAtEntryBBs) { if (RS_DUMP) { std::string r = reg <= R28 ? "r" : "v"; M_LOG << "BB " << entBB << " restore: " << r << (reg - 1) << "\n"; } GetbbSavedRegsEntry(entBB)->InsertEntryReg(reg); } - for (uint32 exitBB : wkCand.restoreAtExitBBs) { + for (BBid exitBB : wkCand.restoreAtExitBBs) { BB *bb = GetId2bb(exitBB); if (bb->GetKind() == BB::kBBIgoto) { CHECK_FATAL(false, "igoto detected"); @@ -525,7 +702,7 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { return true; } -int32 AArch64RegSavesOpt::FindNextOffsetForCalleeSave() const { +int32 AArch64RegSavesOpt::FindCalleeBase() const { int32 offset = static_cast( static_cast(cgFunc->GetMemlayout())->RealStackFrameSize() - (static_cast(cgFunc)->SizeOfCalleeSaved() - (kDivide2 * kIntregBytelen) /* FP/LR */) - @@ -541,16 +718,29 @@ int32 AArch64RegSavesOpt::FindNextOffsetForCalleeSave() const { return offset; } +void AArch64RegSavesOpt::AdjustRegOffsets() { + AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); + int32 regsInProEpilog = aarchCGFunc->GetProEpilogSavedRegs().size() - 2; + if (regsInProEpilog > 0) { + const MapleVector &callees = aarchCGFunc->GetCalleeSavedRegs(); + for (auto reg : callees) { + SKIP_FPLR(reg); + if (regOffset.find(reg) != regOffset.end()) { + regOffset[reg] += regsInProEpilog << 3; + } + } + } +} + void AArch64RegSavesOpt::InsertCalleeSaveCode() { - uint32 bid = 0; + BBid bid = 0; BB *saveBB = cgFunc->GetCurBB(); AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); if (RS_DUMP) { - M_LOG << "Inserting Save: \n"; + M_LOG << "Inserting Save for " << cgFunc->GetName() << ":\n"; } - int32 offset = FindNextOffsetForCalleeSave(); - offset += static_cast((aarchCGFunc->GetProEpilogSavedRegs().size() - 2) << 3); // 2 for R29,RLR 3 for 8 bytes + int32 offset = FindCalleeBase(); for (BB *bb : bfs->sortedBBs) { bid = bb->GetId(); aarchCGFunc->SetSplitBaseOffset(0); @@ -697,14 +887,14 @@ void AArch64RegSavesOpt::Verify(regno_t reg, BB *bb, std::set *vis } void AArch64RegSavesOpt::InsertCalleeRestoreCode() { - uint32 bid = 0; + BBid bid = 0; BB *saveBB = cgFunc->GetCurBB(); AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); if (RS_DUMP) { M_LOG << "Inserting Restore: \n"; } - int32 offset = FindNextOffsetForCalleeSave(); + int32 offset = FindCalleeBase(); for (BB *bb : bfs->sortedBBs) { bid = bb->GetId(); aarchCGFunc->SetSplitBaseOffset(0); @@ -779,15 +969,10 @@ void AArch64RegSavesOpt::InsertCalleeRestoreCode() { /* Callee-save registers save/restore placement optimization */ void AArch64RegSavesOpt::Run() { // DotGenerator::GenerateDot("SR", *cgFunc, cgFunc->GetMirModule(), true, cgFunc->GetName()); - if (Globals::GetInstance()->GetOptimLevel() <= 1) { + if (Globals::GetInstance()->GetOptimLevel() <= 1 || !cgFunc->GetMirModule().IsCModule()) { return; } - -#if ONE_REG_AT_A_TIME - /* only do reg placement on the following register, others in pro/epilog */ - oneAtaTime = true; - oneAtaTimeReg = R25; -#endif + AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); Bfs localBfs(*cgFunc, *memPool); bfs = &localBfs; @@ -797,26 +982,26 @@ void AArch64RegSavesOpt::Run() { PrintBBs(); } -#ifdef REDUCE_COMPLEXITY - CGOptions::EnableRegSavesOpt(); - for (auto bb : bfs->sortedBBs) { - if (bb->GetSuccs().size() > THRESHOLD) { - CGOptions::DisableRegSavesOpt(); - return; - } - } -#endif - /* Determined 1st def and last use of all callee-saved registers used for all BBs */ InitData(); - GetLocalDefUse(); + GenRegDefUse(); - /* Determine save sites at dominators of 1st def with no live-in and - not within loop */ if (CGOptions::UseSsaPreSave()) { + /* Use ssapre */ + if (CheckForUseBeforeDefPath()) { + for (auto reg : aarchCGFunc->GetCalleeSavedRegs()) { + if (reg != RFP && reg != RLR) { + aarchCGFunc->GetProEpilogSavedRegs().push_back(reg); + } + } + return; + } DetermineCalleeSaveLocationsPre(); } else { + /* Determine save sites at dominators of 1st def with no live-in and + not within loop */ + /* Obsolete, to be deleted */ DetermineCalleeSaveLocationsDoms(); } @@ -840,6 +1025,9 @@ void AArch64RegSavesOpt::Run() { } #endif + /* Adjust assigned offsets if there are regs to be saved in prolog */ + AdjustRegOffsets(); + /* Generate callee save instrs at found sites */ InsertCalleeSaveCode(); diff --git a/src/mapleall/maple_be/src/cg/cg_option.cpp b/src/mapleall/maple_be/src/cg/cg_option.cpp index cb1c5be9aa..5184d33d02 100644 --- a/src/mapleall/maple_be/src/cg/cg_option.cpp +++ b/src/mapleall/maple_be/src/cg/cg_option.cpp @@ -774,7 +774,7 @@ void CGOptions::EnableO2() { doLocalRefSpill = true; doCalleeToSpill = true; doRegSavesOpt = false; - useSsaPreSave = false; + useSsaPreSave = true; useSsuPreRestore = true; doWriteRefFieldOpt = true; SetOption(kProEpilogueOpt); -- Gitee From 16cda55ac03cbe6295fc31481ed007b97874b6d2 Mon Sep 17 00:00:00 2001 From: Alfred Huang Date: Mon, 8 Aug 2022 22:53:03 -0700 Subject: [PATCH 2/2] Changed source conforming to functions should not have more than 5 nested block restrictions. --- .../include/cg/aarch64/aarch64_regsaves.h | 5 + .../src/cg/aarch64/aarch64_regsaves.cpp | 528 +++++++++--------- 2 files changed, 278 insertions(+), 255 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h index d7f2eb318d..d6816fd629 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_regsaves.h @@ -169,12 +169,16 @@ class AArch64RegSavesOpt : public RegSavesOpt { void ProcessListOpnd(const BB &bb, Operand &opnd); void ProcessMemOpnd(const BB &bb, Operand &opnd); void ProcessCondOpnd(const BB &bb); + void ProcessOperands(Insn *insn, const BB &bb); void GenAccDefs(); void GenRegDefUse(); bool CheckForUseBeforeDefPath(); void PrintBBs() const; int CheckCriteria(BB *bb, regno_t reg) const; + void CheckCriticalEdge(BB *bb, AArch64reg reg); bool AlreadySavedInDominatorList(const BB *bb, regno_t reg) const; + BB* FindLoopDominator(BB *bb, regno_t reg, bool *done); + void CheckAndRemoveBlksFromCurSavedList(SavedBBInfo *sp, BB *bbDom, regno_t reg); void DetermineCalleeSaveLocationsDoms(); void DetermineCalleeSaveLocationsPre(); bool DetermineCalleeRestoreLocations(); @@ -184,6 +188,7 @@ class AArch64RegSavesOpt : public RegSavesOpt { void InsertCalleeRestoreCode(); void CreateReachingBBs(ReachInfo *rp, BB *bb); BB* RemoveRedundancy(BB *startbb, regno_t reg); + void PrintSaveLocs(AArch64reg reg); void Verify(regno_t reg, BB* bb, std::set *visited, uint32 *s, uint32 *r); void Run() override; diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp index d06adf49ea..fdf2b7ede2 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_regsaves.cpp @@ -23,8 +23,7 @@ namespace maplebe { -#define RS_DUMP GetEnabledDebug() -#define RS_EXTRA (RS_DUMP && true) +#define RS_DUMP 0 #define M_LOG LogInfo::MapleLogger() #define SKIP_FPLR(REG) \ @@ -40,6 +39,9 @@ void AArch64RegSavesOpt::CreateReachingBBs(ReachInfo *rp, BB *bb) { CreateReachingBBs(rp, succ); } } +#if RS_DUMP + M_LOG << " --ReachingBBs for BB " << bb->GetId() << " created\n"; +#endif } void AArch64RegSavesOpt::InitData() { @@ -157,6 +159,57 @@ void AArch64RegSavesOpt::ProcessCondOpnd(const BB &bb) { CollectLiveInfo(bb, rflag, false, true); } +void AArch64RegSavesOpt::ProcessOperands(Insn *insn, const BB &bb) { + const AArch64MD *md = &AArch64CG::kMd[static_cast(insn)->GetMachineOpcode()]; + bool isAsm = (insn->GetMachineOpcode() == MOP_asm); + + uint32 opndNum = insn->GetOperandSize(); + for (uint32 i = 0; i < opndNum; ++i) { + Operand &opnd = insn->GetOperand(i); + OpndProp *regProp = md->operand[i]; + bool isDef = regProp->IsRegDef(); + bool isUse = regProp->IsRegUse(); + if (opnd.IsList()) { + if (isAsm) { + ProcessAsmListOpnd(bb, opnd, i); + } else { + ProcessListOpnd(bb, opnd); + } + } else if (opnd.IsMemoryAccessOperand()) { + ProcessMemOpnd(bb, opnd); + } else if (opnd.IsConditionCode()) { + ProcessCondOpnd(bb); + } else { + CollectLiveInfo(bb, opnd, isDef, isUse); + } + } /* for all operands */ +} + +static +bool IsBackEdge(BB* bb, BB* targ) { + CGFuncLoops *loop = bb->GetLoop(); + if (loop != nullptr && loop->GetHeader() == bb) { + if (find(loop->GetBackedge().begin(), loop->GetBackedge().end(), targ) != loop->GetBackedge().end()) { + return true; + } + } + return false; +} + +static +bool BBHasTerminalCall(BB *bb) { + if (bb->GetKind() == BB::kBBGoto && bb->NumInsn() > 1) { + Insn *insn = bb->GetLastInsn()->GetPrev(); + if (insn->GetMachineOpcode() == MOP_xbl) { + auto *nameOpnd = static_cast(&insn->GetOperand(kInsnFirstOpnd)); + if (nameOpnd->GetName() == "fancy_abort") { + return true; + } + } + } + return false; +} + void AArch64RegSavesOpt::GenAccDefs() { /* Set up accumulated callee def bits in all blocks */ for (auto bb : bfs->sortedBBs) { @@ -166,23 +219,12 @@ void AArch64RegSavesOpt::GenAccDefs() { CalleeBitsType curbbBits = GetBBCalleeBits(GetCalleeBitsDef(), bb->GetId()); int64 n = -1; CalleeBitsType tmp = (CalleeBitsType)n; - CGFuncLoops *loop = bb->GetLoop(); for (auto pred : bb->GetPreds()) { - if (loop != nullptr && loop->GetHeader() == bb) { - if (find(loop->GetBackedge().begin(), loop->GetBackedge().end(), pred) != loop->GetBackedge().end()) { - continue; - } + if (IsBackEdge(bb, pred)) { + continue; } - if (pred->GetKind() == BB::kBBGoto) { - if (pred->NumInsn() > 1) { - Insn *insn = pred->GetLastInsn()->GetPrev(); - if (insn->GetMachineOpcode() == MOP_xbl) { - auto *nameOpnd = static_cast(&insn->GetOperand(kInsnFirstOpnd)); - if (nameOpnd->GetName() == "fancy_abort") { - continue; /* skip unreachable */ - } - } - } + if (BBHasTerminalCall(pred)) { + continue; } tmp &= GetBBCalleeBits(GetCalleeBitsAcc(), pred->GetId()); } @@ -207,61 +249,46 @@ void AArch64RegSavesOpt::GenRegDefUse() { if (!insn->IsMachineInstruction()) { continue; } - - bool isAsm = (insn->GetMachineOpcode() == MOP_asm); - const AArch64MD *md = &AArch64CG::kMd[static_cast(insn)->GetMachineOpcode()]; - uint32 opndNum = insn->GetOperandSize(); - for (uint32 i = 0; i < opndNum; ++i) { - Operand &opnd = insn->GetOperand(i); - OpndProp *regProp = md->operand[i]; - bool isDef = regProp->IsRegDef(); - bool isUse = regProp->IsRegUse(); - if (opnd.IsList()) { - if (isAsm) { - ProcessAsmListOpnd(bb, opnd, i); - } else { - ProcessListOpnd(bb, opnd); - } - } else if (opnd.IsMemoryAccessOperand()) { - ProcessMemOpnd(bb, opnd); - } else if (opnd.IsConditionCode()) { - ProcessCondOpnd(bb); - } else { - CollectLiveInfo(bb, opnd, isDef, isUse); - } - } /* for all operands */ + ProcessOperands(insn, bb); } /* for all insns */ } /* for all sortedBBs */ GenAccDefs(); - if (RS_DUMP) { - M_LOG << "CalleeBits for " << cgFunc->GetName() << ":\n"; - for (BBid i = 1; i < cgFunc->NumBBs(); ++i) { - M_LOG << i << " : " << calleeBitsDef[i] << " " << calleeBitsUse[i] << " " << calleeBitsAcc[i] << "\n"; - } +#if RS_DUMP + M_LOG << "CalleeBits for " << cgFunc->GetName() << ":\n"; + for (BBid i = 1; i < cgFunc->NumBBs(); ++i) { + M_LOG << i << " : " << calleeBitsDef[i] << " " << calleeBitsUse[i] << " " << calleeBitsAcc[i] << "\n"; } +#endif } bool AArch64RegSavesOpt::CheckForUseBeforeDefPath() { /* Check if any block has a use without a def as shown in its accumulated calleeBitsDef from above */ + BBid found = 0; + CalleeBitsType use; + CalleeBitsType acc; for (BBid bid = 0; bid < cgFunc->NumBBs(); ++bid) { - CalleeBitsType use = GetBBCalleeBits(GetCalleeBitsUse(), bid); - CalleeBitsType acc = GetBBCalleeBits(GetCalleeBitsAcc(), bid); + use = GetBBCalleeBits(GetCalleeBitsUse(), bid); + acc = GetBBCalleeBits(GetCalleeBitsAcc(), bid); if ((use & acc) != use) { - if (RS_DUMP) { - CalleeBitsType mask = 1; - for (uint32 i = 0; i < static_cast(sizeof(CalleeBitsType) << 3); ++i) { - regno_t reg = ReverseRegBitMap(i); - if ((use & mask) != 0 && (acc & mask) == 0) { - M_LOG << "R" << reg - 1 << " in BB" << bid << " is in a use before def path\n"; - } - mask <<= 1; - } - } - return true; + found = bid; + break; + } + } + if (found) { +#if RS_DUMP + CalleeBitsType mask = 1; + for (uint32 i = 0; i < static_cast(sizeof(CalleeBitsType) << 3); ++i) { + regno_t reg = ReverseRegBitMap(i); + if ((use & mask) != 0 && (acc & mask) == 0) { + M_LOG << "R" << reg - 1 << " in BB" << found << " is in a use before def path\n"; } + mask <<= 1; + } +#endif + return true; } return false; } @@ -315,22 +342,19 @@ int32 AArch64RegSavesOpt::CheckCriteria(BB *bb, regno_t reg) const { bool AArch64RegSavesOpt::AlreadySavedInDominatorList(const BB *bb, regno_t reg) const { BB *aBB = GetDomInfo()->GetDom(bb->GetId()); - if (RS_DUMP) { - M_LOG << "Checking dom list starting " << bb->GetId() << " for saved R" << (reg - 1) << ":\n "; - } +#if RS_DUMP + M_LOG << "Checking dom list starting " << bb->GetId() << " for saved R" << (reg - 1) << ":\n "; +#endif while (!aBB->GetPreds().empty()) { /* can't go beyond prolog */ - if (RS_DUMP) { - M_LOG << aBB->GetId() << " "; - } +#if RS_DUMP + M_LOG << aBB->GetId() << " "; +#endif int t = CheckCriteria(aBB, reg); if (t != 0) { - if (RS_DUMP) { - if (t == 1) { - M_LOG << " --R" << (reg - 1) << " saved here, skip!\n"; - } else { - M_LOG << " --R" << (reg - 1) << " has livein/out, skip!\n"; - } - } +#if RS_DUMP + std::string str = t == 1 ? " saved here, skip!\n" : " has livein/out, skip!\n"; + M_LOG << " --R" << (reg - 1) << str; +#endif return true; /* previously saved, inspect next reg */ } aBB = GetDomInfo()->GetDom(aBB->GetId()); @@ -338,7 +362,7 @@ bool AArch64RegSavesOpt::AlreadySavedInDominatorList(const BB *bb, regno_t reg) return false; /* not previously saved, to save at bb */ } -#if REMOVE_DOM_REDUNDANCY +#ifdef REMOVE_DOM_REDUNDANCY /* Return true if reg is already to be saved in all paths to target from already saved BBs */ BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { @@ -363,9 +387,6 @@ BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { if (rp->GetBBList().empty()) { (void)visited.clear(); CreateReachingBBs(rp, from); - if (RS_DUMP) { - M_LOG << " --ReachingBBs for BB " << from->GetId() << " created\n"; - } } if (rp->ContainInReachingBBs(tbid)) { /* BB reaches curbb */ change = true; @@ -382,16 +403,13 @@ BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { remove these blks from bbSavedRegs */ ReachInfo *rp = GetReachingEntry(targ->GetId()); if (rp->GetBBList().empty()) { - if (RS_DUMP) { - M_LOG << " --ReachingBBs for BB " << targ->GetId() << " created\n"; - } CreateReachingBBs(rp, targ); } for (BB *bb : saveSet) { if (bb->GetId() == targ->GetId()) { - if (RS_DUMP) { - M_LOG << " --R" << reg - 1 << " already saved in BB" << targ->GetId()<< "\n"; - } +#if RS_DUMP + M_LOG << " --R" << reg - 1 << " already saved in BB" << targ->GetId()<< "\n"; +#endif continue; } else if (bb->GetPreds().empty()) { continue; @@ -399,9 +417,9 @@ BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { if (rp->ContainInReachingBBs(bb->GetId())) { saveSet.erase(bb); bbSavedRegs[bb->GetId()]->RemoveSaveReg(reg); - if (RS_DUMP) { - M_LOG << " --R" << (reg - 1) << " save removed from BB" << bb->GetId() << "\n"; - } +#if RS_DUMP + M_LOG << " --R" << (reg - 1) << " save removed from BB" << bb->GetId() << "\n"; +#endif } } @@ -409,89 +427,99 @@ BB* AArch64RegSavesOpt::RemoveRedundancy(BB *target, regno_t reg) { } #endif +BB* AArch64RegSavesOpt::FindLoopDominator(BB *bb, regno_t reg, bool *done) { + BB *bbDom = bb; + while (bbDom->GetLoop() != nullptr) { + bbDom = GetDomInfo()->GetDom(bbDom->GetId()); + if (CheckCriteria(bbDom, reg) != 0) { + *done = true; + break; + } + ASSERT(bbDom, "Can't find dominator for save location"); + } + return bbDom; +} + +/* If the newly found blk is a dominator of blk(s) in the current + to be saved list, remove these blks from bbSavedRegs */ +void AArch64RegSavesOpt::CheckAndRemoveBlksFromCurSavedList(SavedBBInfo *sp, BB *bbDom, regno_t reg) { + for (BB *sbb : sp->GetBBList()) { + for (BB *abb = sbb; !abb->GetPreds().empty();) { + if (abb->GetId() == bbDom->GetId()) { + /* Found! Don't plan to save in abb */ + sp->RemoveBB(sbb); + bbSavedRegs[sbb->GetId()]->RemoveSaveReg(reg); +#if RS_DUMP + M_LOG << " --R" << (reg - 1) << " save removed from BB" << sbb->GetId() << "\n"; +#endif + break; + } + abb = GetDomInfo()->GetDom(abb->GetId()); + } + } +} + /* Determine callee-save regs save locations and record them in bbSavedRegs. Save is needed for a 1st def callee-save register at its dominator block outside any loop. */ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsDoms() { - if (RS_DUMP) { - M_LOG << "Determining regsave sites using dom list for " << cgFunc->GetName() << ":\n"; - } +#if RS_DUMP + M_LOG << "Determining regsave sites using dom list for " << cgFunc->GetName() << ":\n"; +#endif for (auto *bb : bfs->sortedBBs) { - if (RS_DUMP) { - M_LOG << "BB: " << bb->GetId() << "\n"; - } +#if RS_DUMP + M_LOG << "BB: " << bb->GetId() << "\n"; +#endif CalleeBitsType c = GetBBCalleeBits(GetCalleeBitsDef(), bb->GetId()); if (c == 0) { continue; } CalleeBitsType mask = 1; for (uint32 i = 0; i < static_cast(sizeof(CalleeBitsType) << 3); ++i) { - if ((c & mask) != 0) { - MapleSet &liveIn = bb->GetLiveInRegNO(); - regno_t reg = ReverseRegBitMap(i); - if (liveIn.find(reg) == liveIn.end()) { /* not livein */ - BB *bbDom = bb; /* start from current BB */ - bool done = false; - while (bbDom->GetLoop() != nullptr) { - bbDom = GetDomInfo()->GetDom(bbDom->GetId()); - if (CheckCriteria(bbDom, reg) != 0) { - done = true; - break; - } - ASSERT(bbDom, "Can't find dominator for save location"); - } - if (done) { - mask <<= 1; - continue; - } + MapleSet &liveIn = bb->GetLiveInRegNO(); + regno_t reg = ReverseRegBitMap(i); + if ((c & mask) != 0 && liveIn.find(reg) == liveIn.end()) { /* not livein */ + BB *bbDom = bb; /* start from current BB */ + bool done = false; + bbDom = FindLoopDominator(bbDom, reg, &done); + if (done) { + mask <<= 1; + continue; + } -#if REMOVE_DOM_REDUNDANCY - bbDom = RemoveRedundancy(bbDom, reg); - if (regSavedBBs[i] == nullptr) { - regSavedBBs[i] = memPool->New(alloc); - } - regSavedBBs[i]->InsertBB(bbDom); +#ifdef REMOVE_DOM_REDUNDANCY + bbDom = RemoveRedundancy(bbDom, reg); + if (regSavedBBs[i] == nullptr) { + regSavedBBs[i] = memPool->New(alloc); + } + regSavedBBs[i]->InsertBB(bbDom); #endif - /* Check if a dominator of bbDom was already a location to save */ - if (AlreadySavedInDominatorList(bbDom, reg)) { - mask <<= 1; - continue; /* no need to save again, next reg */ - } + /* Check if a dominator of bbDom was already a location to save */ + if (AlreadySavedInDominatorList(bbDom, reg)) { + mask <<= 1; + continue; /* no need to save again, next reg */ + } - /* If the newly found blk is a dominator of blk(s) in the current - to be saved list, remove these blks from bbSavedRegs */ - uint32 creg = i; - SavedBBInfo *sp = regSavedBBs[creg]; - if (sp == nullptr) { - regSavedBBs[creg] = memPool->New(alloc); - } else { - for (BB *sbb : sp->GetBBList()) { - for (BB *abb = sbb; !abb->GetPreds().empty();) { - if (abb->GetId() == bbDom->GetId()) { - /* Found! Don't plan to save in abb */ - sp->RemoveBB(sbb); - bbSavedRegs[sbb->GetId()]->RemoveSaveReg(reg); - if (RS_DUMP) { - M_LOG << " --R" << (reg - 1) << " save removed from BB" << sbb->GetId() << "\n"; - } - break; - } - abb = GetDomInfo()->GetDom(abb->GetId()); - } - } - } - regSavedBBs[creg]->InsertBB(bbDom); + /* If the newly found blk is a dominator of blk(s) in the current + to be saved list, remove these blks from bbSavedRegs */ + uint32 creg = i; + SavedBBInfo *sp = regSavedBBs[creg]; + if (sp == nullptr) { + regSavedBBs[creg] = memPool->New(alloc); + } else { + CheckAndRemoveBlksFromCurSavedList(sp, bbDom, reg); + } + regSavedBBs[creg]->InsertBB(bbDom); - BBid bid = bbDom->GetId(); - if (RS_DUMP) { - M_LOG << " --R" << (reg - 1); - M_LOG << " to save in " << bid << "\n"; - } - SavedRegInfo *ctx = GetbbSavedRegsEntry(bid); - if (!ctx->ContainSaveReg(reg)) { - ctx->InsertSaveReg(reg); - } + BBid bid = bbDom->GetId(); +#if RS_DUMP + M_LOG << " --R" << (reg - 1); + M_LOG << " to save in " << bid << "\n"; +#endif + SavedRegInfo *ctx = GetbbSavedRegsEntry(bid); + if (!ctx->ContainSaveReg(reg)) { + ctx->InsertSaveReg(reg); } } mask <<= 1; @@ -507,9 +535,9 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsDoms() { void AArch64RegSavesOpt::DetermineCalleeSaveLocationsPre() { AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); MapleAllocator sprealloc(memPool); - if (RS_DUMP) { - M_LOG << "Determining regsave sites using ssa_pre for " << cgFunc->GetName() << ":\n"; - } +#if RS_DUMP + M_LOG << "Determining regsave sites using ssa_pre for " << cgFunc->GetName() << ":\n"; +#endif const MapleVector &callees = aarchCGFunc->GetCalleeSavedRegs(); int32 offset = FindCalleeBase(); for (auto reg : callees) { @@ -559,24 +587,24 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsPre() { if (reg2 != kRinvalid && std::find(pe.begin(), pe.end(), reg2) == pe.end()) { pe.push_back(reg2); } - if (RS_DUMP) { - M_LOG << "Save R" << (reg1 - 1) << " n/a, do in Pro/Epilog\n"; - if (reg2 != kRinvalid) { - M_LOG << " R " << (reg2 - 1) << " n/a, do in Pro/Epilog\n"; - } +#if RS_DUMP + M_LOG << "Save R" << (reg1 - 1) << " n/a, do in Pro/Epilog\n"; + if (reg2 != kRinvalid) { + M_LOG << " R " << (reg2 - 1) << " n/a, do in Pro/Epilog\n"; } +#endif continue; } if (!wkCand.saveAtEntryBBs.empty()) { for (BBid entBB : wkCand.saveAtEntryBBs) { - if (RS_DUMP) { - std::string r = reg1 <= R28 ? "R" : "V"; - M_LOG << "BB " << entBB << " save for : " << r << (reg1 - 1) << "\n"; - if (reg2 != kRinvalid) { - std::string r = reg2 <= R28 ? "R" : "V"; - M_LOG << " : " << r << (reg2 - 1) << "\n"; - } +#if RS_DUMP + std::string r = reg1 <= R28 ? "R" : "V"; + M_LOG << "BB " << entBB << " save for : " << r << (reg1 - 1) << "\n"; + if (reg2 != kRinvalid) { + std::string r = reg2 <= R28 ? "R" : "V"; + M_LOG << " : " << r << (reg2 - 1) << "\n"; } +#endif GetbbSavedRegsEntry(entBB)->InsertSaveReg(reg1); if (reg2 != kRinvalid) { GetbbSavedRegsEntry(entBB)->InsertSaveReg(reg2); @@ -586,14 +614,24 @@ void AArch64RegSavesOpt::DetermineCalleeSaveLocationsPre() { } } +void AArch64RegSavesOpt::CheckCriticalEdge(BB *bb, AArch64reg reg) { + for (BB *sbb : bb->GetSuccs()) { + if (sbb->GetPreds().size() > 1) { + CHECK_FATAL(false, "critical edge detected"); + } + /* To insert at all succs */ + GetbbSavedRegsEntry(sbb->GetId())->InsertEntryReg(reg); + } +} + /* Determine calleesave regs restore locations by calling ssu-pre, previous bbSavedRegs memory is cleared and restore locs recorded in it */ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); MapleAllocator sprealloc(memPool); - if (RS_DUMP) { - M_LOG << "Determining Callee Restore Locations:\n"; - } +#if RS_DUMP + M_LOG << "Determining Callee Restore Locations:\n"; +#endif const MapleVector &callees = aarchCGFunc->GetCalleeSavedRegs(); for (auto reg : callees) { SKIP_FPLR(reg); @@ -626,9 +664,9 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { for (auto bbid : rset) { BB *bb = GetId2bb(bbid); if (bb->GetKind() == BB::kBBGoto && bb->NumInsn() == 1) { - if (RS_DUMP) { - M_LOG << "Restores in splitted empty BB" << bbid << "\n"; - } +#if RS_DUMP + M_LOG << "Restores in splitted empty BB" << bbid << "\n"; +#endif // wkCand.restoreAtEpilog = true; // break; aarchCGFunc->GetProEpilogSavedRegs().clear(); @@ -644,27 +682,25 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { in prolog/epilog */ for (size_t bid = 1; bid < bbSavedRegs.size(); ++bid) { SavedRegInfo *sp = bbSavedRegs[bid]; - if (sp != nullptr && !sp->GetSaveSet().empty()) { - if (sp->ContainSaveReg(reg)) { - sp->RemoveSaveReg(reg); - } + if (sp != nullptr && !sp->GetSaveSet().empty() && sp->ContainSaveReg(reg)) { + sp->RemoveSaveReg(reg); } } MapleVector &pe = aarchCGFunc->GetProEpilogSavedRegs(); if (std::find(pe.begin(), pe.end(), reg) == pe.end()) { pe.push_back(reg); } - if (RS_DUMP) { - M_LOG << "Restore R" << (reg - 1) << " n/a, do in Pro/Epilog\n"; - } +#if RS_DUMP + M_LOG << "Restore R" << (reg - 1) << " n/a, do in Pro/Epilog\n"; +#endif continue; } if (!wkCand.restoreAtEntryBBs.empty() || !wkCand.restoreAtExitBBs.empty()) { for (BBid entBB : wkCand.restoreAtEntryBBs) { - if (RS_DUMP) { - std::string r = reg <= R28 ? "r" : "v"; - M_LOG << "BB " << entBB << " restore: " << r << (reg - 1) << "\n"; - } +#if RS_DUMP + std::string r = reg <= R28 ? "r" : "v"; + M_LOG << "BB " << entBB << " restore: " << r << (reg - 1) << "\n"; +#endif GetbbSavedRegsEntry(entBB)->InsertEntryReg(reg); } for (BBid exitBB : wkCand.restoreAtExitBBs) { @@ -681,21 +717,15 @@ bool AArch64RegSavesOpt::DetermineCalleeRestoreLocations() { sp->InsertExitReg(reg); sp->insertAtLastMinusOne = true; } else if (bb->GetSuccs().size() > 1) { - for (BB *sbb : bb->GetSuccs()) { - if (sbb->GetPreds().size() > 1) { - CHECK_FATAL(false, "critical edge detected"); - } - /* To insert at all succs */ - GetbbSavedRegsEntry(sbb->GetId())->InsertEntryReg(reg); - } + CheckCriticalEdge(bb, reg); } else { /* otherwise, BB_FT etc */ GetbbSavedRegsEntry(exitBB)->InsertExitReg(reg); } - if (RS_DUMP) { +#if RS_DUMP std::string r = reg <= R28 ? "R" : "V"; M_LOG << "BB " << exitBB << " restore: " << r << (reg - 1) << "\n"; - } +#endif } } } @@ -726,7 +756,7 @@ void AArch64RegSavesOpt::AdjustRegOffsets() { for (auto reg : callees) { SKIP_FPLR(reg); if (regOffset.find(reg) != regOffset.end()) { - regOffset[reg] += regsInProEpilog << 3; + regOffset[reg] += regsInProEpilog * kBitsPerByte; } } } @@ -737,9 +767,9 @@ void AArch64RegSavesOpt::InsertCalleeSaveCode() { BB *saveBB = cgFunc->GetCurBB(); AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); - if (RS_DUMP) { - M_LOG << "Inserting Save for " << cgFunc->GetName() << ":\n"; - } +#if RS_DUMP + M_LOG << "Inserting Save for " << cgFunc->GetName() << ":\n"; +#endif int32 offset = FindCalleeBase(); for (BB *bb : bfs->sortedBBs) { bid = bb->GetId(); @@ -762,9 +792,9 @@ void AArch64RegSavesOpt::InsertCalleeSaveCode() { if (firstHalf == kRinvalid) { /* 1st half in reg pair */ firstHalf = reg; - if (RS_DUMP && reg > 0) { - M_LOG << r << (reg - 1) << " save in BB" << bid << " Offset = " << regOffset[reg]<< "\n"; - } +#if RS_DUMP + M_LOG << r << (reg - 1) << " save in BB" << bid << " Offset = " << regOffset[reg]<< "\n"; +#endif } else { if (regOffset[reg] == (regOffset[firstHalf] + k8ByteSize)) { /* firstHalf & reg consecutive, make regpair */ @@ -782,9 +812,9 @@ void AArch64RegSavesOpt::InsertCalleeSaveCode() { static_cast(regOffset[reg])); } firstHalf = kRinvalid; - if (RS_DUMP) { - M_LOG << r << (reg - 1) << " save in BB" << bid << " Offset = " << regOffset[reg]<< "\n"; - } +#if RS_DUMP + M_LOG << r << (reg - 1) << " save in BB" << bid << " Offset = " << regOffset[reg]<< "\n"; +#endif } } @@ -803,20 +833,27 @@ void AArch64RegSavesOpt::InsertCalleeSaveCode() { cgFunc->SetCurBB(*saveBB); } +void AArch64RegSavesOpt::PrintSaveLocs(AArch64reg reg) { + M_LOG << " for save @BB [ "; + for (size_t b = 1; b < bbSavedRegs.size(); ++b) { + if (bbSavedRegs[b] != nullptr && bbSavedRegs[b]->ContainSaveReg(reg)) { + M_LOG << b << " "; + } + } + M_LOG << "]\n"; +} + /* DFS to verify the save/restore are in pair(s) within a path */ +#ifdef VERIFY void AArch64RegSavesOpt::Verify(regno_t reg, BB *bb, std::set *visited, uint32 *s, uint32 *r) { (void)visited->insert(bb); BBId bid = bb->GetId(); - if (RS_EXTRA) { - M_LOG << bid << ","; /* path trace can be long */ - } + M_LOG << bid << ","; /* path trace can be long */ if (bbSavedRegs[bid] != nullptr) { bool entryRestoreMet = false; if (bbSavedRegs[bid]->ContainEntryReg(reg)) { - if (RS_EXTRA) { - M_LOG << "[^" << bid << "],"; // entry restore found - } + M_LOG << "[^" << bid << "],"; // entry restore found if (*s == 0) { M_LOG << "Alert: nR@" << bid << " found w/o save\n"; return; @@ -827,9 +864,7 @@ void AArch64RegSavesOpt::Verify(regno_t reg, BB *bb, std::set *vis entryRestoreMet = true; } if (bbSavedRegs[bid]->ContainSaveReg(reg)) { - if (RS_EXTRA) { - M_LOG << "[" << bid << "],"; // save found - } + M_LOG << "[" << bid << "],"; // save found if (*s != 0 && !entryRestoreMet) { /* another save found before last save restored */ M_LOG << "Alert: save@" << bid << " found after save@" << *s << "\n"; @@ -841,9 +876,7 @@ void AArch64RegSavesOpt::Verify(regno_t reg, BB *bb, std::set *vis *s = bid; } if (bbSavedRegs[bid]->ContainExitReg(reg)) { - if (RS_EXTRA) { - M_LOG << "[" << bid << "$],"; // exit restore found - } + M_LOG << "[" << bid << "$],"; // exit restore found if (*s == 0) { M_LOG << "Alert: xR@" << bid << " found w/o save\n"; return; @@ -885,15 +918,16 @@ void AArch64RegSavesOpt::Verify(regno_t reg, BB *bb, std::set *vis } } } +#endif void AArch64RegSavesOpt::InsertCalleeRestoreCode() { BBid bid = 0; BB *saveBB = cgFunc->GetCurBB(); AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); - if (RS_DUMP) { - M_LOG << "Inserting Restore: \n"; - } +#if RS_DUMP + M_LOG << "Inserting Restore: \n"; +#endif int32 offset = FindCalleeBase(); for (BB *bb : bfs->sortedBBs) { bid = bb->GetId(); @@ -909,19 +943,11 @@ void AArch64RegSavesOpt::InsertCalleeRestoreCode() { for (auto areg : sp->GetEntrySet()) { AArch64reg reg = static_cast(areg); offset = static_cast(regOffset[areg]); - if (RS_DUMP) { - std::string r = reg <= R28 ? "R" : "V"; - M_LOG << r << (reg - 1) << " entry restore in BB " << bid << " Saved Offset = " << offset << "\n"; - if (RS_EXTRA) { - M_LOG << " for save @BB [ "; - for (size_t b = 1; b < bbSavedRegs.size(); ++b) { - if (bbSavedRegs[b] != nullptr && bbSavedRegs[b]->ContainSaveReg(reg)) { - M_LOG << b << " "; - } - } - M_LOG << "]\n"; - } - } +#if RS_DUMP + std::string r = reg <= R28 ? "R" : "V"; + M_LOG << r << (reg - 1) << " entry restore in BB " << bid << " Saved Offset = " << offset << "\n"; + PrintSaveLocs(reg); +#endif /* restore is always the same from saved offset */ RegType regType = AArch64isa::IsGPRegister(reg) ? kRegTyInt : kRegTyFloat; @@ -937,17 +963,11 @@ void AArch64RegSavesOpt::InsertCalleeRestoreCode() { for (auto areg : sp->GetExitSet()) { AArch64reg reg = static_cast(areg); offset = static_cast(regOffset[areg]); - if (RS_DUMP) { - std::string r = reg <= R28 ? "R" : "V"; - M_LOG << r << (reg - 1) << " exit restore in BB " << bid << " Offset = " << offset << "\n"; - M_LOG << " for save @BB [ "; - for (size_t b = 1; b < bbSavedRegs.size(); ++b) { - if (bbSavedRegs[b] != nullptr && bbSavedRegs[b]->ContainSaveReg(reg)) { - M_LOG << b << " "; - } - } - M_LOG << "]\n"; - } +#if RS_DUMP + std::string r = reg <= R28 ? "R" : "V"; + M_LOG << r << (reg - 1) << " exit restore in BB " << bid << " Offset = " << offset << "\n"; + PrintSaveLocs(reg); +#endif /* restore is always single from saved offset */ RegType regType = AArch64isa::IsGPRegister(reg) ? kRegTyInt : kRegTyFloat; @@ -977,10 +997,10 @@ void AArch64RegSavesOpt::Run() { Bfs localBfs(*cgFunc, *memPool); bfs = &localBfs; bfs->ComputeBlockOrder(); - if (RS_DUMP) { - M_LOG << "##Calleeregs Placement for: " << cgFunc->GetName() << "\n"; - PrintBBs(); - } +#if RS_DUMP + M_LOG << "##Calleeregs Placement for: " << cgFunc->GetName() << "\n"; + PrintBBs(); +#endif /* Determined 1st def and last use of all callee-saved registers used for all BBs */ @@ -1012,16 +1032,14 @@ void AArch64RegSavesOpt::Run() { #ifdef VERIFY /* Verify saves/restores are in pair */ - if (RS_DUMP) { - std::vector rlist = { R19, R20, R21, R22, R23, R24, R25, R26, R27, R28 }; - for (auto reg : rlist) { - M_LOG << "Verify calleeregs_placement data for R" << (reg - 1) << ":\n"; - std::set visited; - uint32 saveBid = 0; - uint32 restoreBid = 0; - Verify(reg, cgFunc->GetFirstBB(), &visited, &saveBid, &restoreBid); - M_LOG << "\nVerify Done\n"; - } + std::vector rlist = { R19, R20, R21, R22, R23, R24, R25, R26, R27, R28 }; + for (auto reg : rlist) { + M_LOG << "Verify calleeregs_placement data for R" << (reg - 1) << ":\n"; + std::set visited; + uint32 saveBid = 0; + uint32 restoreBid = 0; + Verify(reg, cgFunc->GetFirstBB(), &visited, &saveBid, &restoreBid); + M_LOG << "\nVerify Done\n"; } #endif -- Gitee