From 1b59fd090a261b95f794828160e999d4700db922 Mon Sep 17 00:00:00 2001 From: William Chen Date: Wed, 25 Aug 2021 19:54:21 -0700 Subject: [PATCH 1/3] reg rename for switch regions. Done either before color RA or during. --- .../include/cg/aarch64/aarch64_ra_opt.h | 67 ++- src/mapleall/maple_be/include/cg/cg_option.h | 49 +- src/mapleall/maple_be/include/cg/cgfunc.h | 9 + .../src/cg/aarch64/aarch64_color_ra.cpp | 10 + .../src/cg/aarch64/aarch64_ra_opt.cpp | 449 +++++++++++++++++- .../src/cg/aarch64/aarch64_reg_alloc.cpp | 1 + src/mapleall/maple_be/src/cg/cg_option.cpp | 8 +- 7 files changed, 554 insertions(+), 39 deletions(-) diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_ra_opt.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_ra_opt.h index 85e65e96f7..2a59e2386d 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_ra_opt.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_ra_opt.h @@ -21,6 +21,7 @@ #include "aarch64_cg.h" #include "aarch64_insn.h" #include "aarch64_operand.h" +#include "aarch64_color_ra.h" namespace maplebe { class X0OptInfo { @@ -96,6 +97,25 @@ class RaX0Opt { CGFunc *cgFunc; }; +class CaseMemberInfo { + public: + CaseMemberInfo(MemPool *pool) : memPool(pool), + alloc(pool), + members(alloc.Adapter()) {} + + ~CaseMemberInfo() = default; + + class LinkNode { + public: + }; + + MemPool *memPool; + MapleAllocator alloc; + BB *head; + MapleList members; + CaseMemberInfo *next; +}; + class VregRenameInfo { public: VregRenameInfo() = default; @@ -112,32 +132,73 @@ class VregRenameInfo { uint8 innerMostloopLevelSeen = 0; }; +class SwitchVregInfo { + public: + SwitchVregInfo(MemPool *pool) : memPool(pool), + alloc(pool), + inRegion(alloc.Adapter()), + regionHasDef(alloc.Adapter()), + regionHasUse(alloc.Adapter()) {} + MemPool *memPool; + MapleAllocator alloc; + MapleUnorderedSet inRegion; + MapleUnorderedMap regionHasDef; + MapleUnorderedMap regionHasUse; + uint32 globalCount = 0; +}; + class VregRename { public: VregRename(CGFunc *func, MemPool *pool) : cgFunc(func), memPool(pool), alloc(pool), - renameInfo(alloc.Adapter()) { - renameInfo.resize(cgFunc->GetMaxRegNum()); + renameInfo(alloc.Adapter()), + caseRegInfo(alloc.Adapter()) { + renameInfo.resize(cgFunc->GetMaxRegNum() + 1); + caseRegInfo.resize(cgFunc->GetMaxRegNum() + 1); ccRegno = static_cast(&cgFunc->GetOrCreateRflag())->GetRegisterNumber(); }; + std::string PhaseName() const { + return "VregRename"; + } + void PrintRenameInfo(regno_t regno) const; void PrintAllRenameInfo() const; + void PrintCaseRegInfo(regno_t regno) const; + void PrintAllCaseRegInfo() const; + void PrintSwitchRegion() const; + VregRenameInfo *CreateVregRenameInfo(regno_t reg); + SwitchVregInfo *CreateCaseVregInfo(regno_t reg); void RenameFindLoopVregs(const CGFuncLoops *loop); void RenameFindVregsToRename(const CGFuncLoops *loop); + void RenameSwitchRegionReg(RegOperand *ropnd, BB *headBB, const MapleList &members); + bool RenameProfitableSwitchVreg(RegOperand *ropnd, BB *headBB, const MapleList &members); + void DetectSwitchRegions(); + void TraverseSwitchCase(std::queue &BBQueue, std::vector &visited, std::set &members); + void RegionTraverseVreg(BB *headBB, std::set &members); + void RegionFindVregForRename(); bool IsProfitableToRename(VregRenameInfo *info); - void RenameProfitableVreg(RegOperand *ropnd, const CGFuncLoops *loop); + bool RenameProfitableVreg(RegOperand *ropnd, const CGFuncLoops *loop); void RenameGetFuncVregInfo(); void UpdateVregInfo(regno_t reg, BB *bb, bool isInner, bool isDef); + void UpdateVregInfoForRegion(BB *headBB, regno_t reg, bool isDef); void VregLongLiveRename(); + void RenameLoopAndSwitch(MapleVector &lrVec); + void FindInnerLoop(const CGFuncLoops *loop, MapleVector &lrVec); + void LoopRenameRegister(const CGFuncLoops *loop, MapleVector &lrVec); + void SwitchRenameRegister(MapleVector &lrVec); CGFunc *cgFunc; MemPool *memPool; MapleAllocator alloc; Bfs *bfs = nullptr; + CaseMemberInfo *caseInfo = nullptr; MapleVector renameInfo; + MapleVector caseRegInfo; + uint32 numCases = 0; + uint32 maxBBNum = 0; uint32 maxRegnoSeen = 0; regno_t ccRegno; }; diff --git a/src/mapleall/maple_be/include/cg/cg_option.h b/src/mapleall/maple_be/include/cg/cg_option.h index 9974fb59f2..d14b9187f2 100644 --- a/src/mapleall/maple_be/include/cg/cg_option.h +++ b/src/mapleall/maple_be/include/cg/cg_option.h @@ -663,16 +663,47 @@ class CGOptions : public MapleDriverOptionBase { static bool DoGlobalOpt() { return doGlobalOpt; } - static void EnableVregRename() { - doVregRename = true; - } - static void DisableVregRename() { - doVregRename = false; + /* The first two bits tells when to run rename + * bit 1 : enable/disable rename before RA + * bit 2 : enable/disable rename in RA + * + * The next two bits turns off either rename + * bit 3 : disable loop rename + * bit 4 : disable switch rename + */ + static void EnableVregRenameBeforeRA() { + doVregRename |= 0x1; + DisableVregRenameInRA(); } - - static bool DoVregRename() { - return doVregRename; + static void EnableVregRenameInRA() { + doVregRename |= 0x2; + DisableVregRenameBeforeRA(); + } + static void DisableVregRenameBeforeRA() { + doVregRename &= 0x2; + } + static void DisableVregRenameInRA() { + doVregRename &= 0x1; + } + static bool DoVregRenameBeforeRA() { + return ((doVregRename & 0x1) == 0x1); + } + static bool DoVregRenameInRA() { + return ((doVregRename & 0x2) == 0x2); + } + static bool DoLoopRename() { + return ((doVregRename & 0x4) == 0); + } + static bool DoSwitchRename() { + return ((doVregRename & 0x8) == 0); + } + static void SetVregRenameMode(uint8 mode) { + if ((mode & 0x1) && (mode & 0x2)) { + doVregRename = 0x2 | (mode & 0x4) | (mode & 0x8); + } else { + doVregRename = mode; + } } static void EnableMultiPassColorRA() { @@ -1113,7 +1144,7 @@ class CGOptions : public MapleDriverOptionBase { static bool doICO; static bool doStoreLoadOpt; static bool doGlobalOpt; - static bool doVregRename; + static uint8 doVregRename; static bool doMultiPassColorRA; static bool doPrePeephole; static bool doPeephole; diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index caf94d5c19..89146982bd 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -944,6 +944,14 @@ class CGFunc { return hasAsm; } + bool DoRename() { + return doRename; + } + + void SetDoRename(bool cond) { + hasAsm = cond; + } + protected: uint32 firstMapleIrVRegNO = 200; /* positioned after physical regs */ uint32 firstNonPregVRegNO; @@ -1069,6 +1077,7 @@ class CGFunc { static constexpr int kRegIncrStepLen = 80; /* reg number increate step length */ const MapleString shortFuncName; bool hasAsm = false; + bool doRename = false; }; /* class CGFunc */ MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgLayoutFrame, maplebe::CGFunc) diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_color_ra.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_color_ra.cpp index 45fbba1703..40f897b25b 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_color_ra.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_color_ra.cpp @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "aarch64_color_ra.h" +#include "aarch64_ra_opt.h" #include #include #include "aarch64_cg.h" @@ -3435,6 +3436,9 @@ void GraphColorRegAllocator::GenerateSpillFillRegs(Insn &insn) { RegOperand *GraphColorRegAllocator::CreateSpillFillCode(RegOperand &opnd, Insn &insn, uint32 spillCnt, bool isdef) { regno_t vregno = opnd.GetRegisterNumber(); + if (vregno >= lrVec.size()) { + return nullptr; + } LiveRange *lr = lrVec[vregno]; if (lr != nullptr && lr->IsSpilled()) { AArch64CGFunc *a64cgfunc = static_cast(cgFunc); @@ -4009,6 +4013,12 @@ void GraphColorRegAllocator::FinalizeRegisters() { } LogInfo::MapleLogger() << "\n"; } + if (cgFunc->DoRename() && CGOptions::DoVregRenameInRA()) { + cgFunc->SetDoRename(false); + VregRename rename(cgFunc, memPool); + rename.VregLongLiveRename(); + rename.RenameLoopAndSwitch(lrVec); + } SpillLiveRangeForSpills(); return; } diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_ra_opt.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_ra_opt.cpp index 263be1a1fd..04a4c5b249 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_ra_opt.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_ra_opt.cpp @@ -19,6 +19,9 @@ namespace maplebe { using namespace std; + +#define RENAME_DUMP CG_DEBUG_FUNC(*cgFunc) + bool RaX0Opt::PropagateX0CanReplace(Operand *opnd, regno_t replaceReg) const { if (opnd != nullptr) { RegOperand *regopnd = static_cast(opnd); @@ -319,6 +322,70 @@ void VregRename::PrintAllRenameInfo() const { } } +void VregRename::PrintCaseRegInfo(regno_t regno) const { + SwitchVregInfo *info = (regno <= maxRegnoSeen) ? caseRegInfo[regno] : nullptr; + if (info == nullptr) { + return; + } + LogInfo::MapleLogger() << "reg: " << regno; + if (info->inRegion.size()) { + LogInfo::MapleLogger() << " inRegion:"; + for (auto *bb : info->inRegion) { + LogInfo::MapleLogger() << bb->GetId() << ","; + } + } + if (info->regionHasDef.size()) { + LogInfo::MapleLogger() << "regionHasDef"; + for (auto pr : info->regionHasDef) { + LogInfo::MapleLogger() << "(" << pr.first << "," << pr.second << ")"; + } + } + if (info->regionHasUse.size()) { + LogInfo::MapleLogger() << "regionHasUse"; + for (auto pr : info->regionHasUse) { + LogInfo::MapleLogger() << "(" << pr.first << "," << pr.second << ")"; + } + } + std::cout << " gCnt:" << info->globalCount << "\n"; +} + +void VregRename::PrintAllCaseRegInfo() const { + for (uint32 regno = 0; regno < cgFunc->GetMaxRegNum(); ++regno) { + PrintCaseRegInfo(regno); + } +} + +void VregRename::PrintSwitchRegion() const { + for (CaseMemberInfo *info = caseInfo; info != nullptr; info = info->next) { + std::cout << "Head(" << info->head->GetId() << ") "; + std::cout << "Members("; + for (auto *bb : info->members) { + std::cout << bb->GetId() << ","; + } + std::cout << ")\n"; + } +} + +VregRenameInfo *VregRename::CreateVregRenameInfo(regno_t vreg) { + if (vreg > maxRegnoSeen) { + maxRegnoSeen = vreg; + renameInfo.resize(maxRegnoSeen + 1); + } + VregRenameInfo *info = memPool->New(); + renameInfo[vreg] = info; + return info; +} + +SwitchVregInfo *VregRename::CreateCaseVregInfo(regno_t vreg) { + if (vreg > maxRegnoSeen) { + maxRegnoSeen = vreg; + caseRegInfo.resize(maxRegnoSeen + 1); + } + SwitchVregInfo *info = memPool->New(memPool); + caseRegInfo[vreg] = info; + return info; +} + bool VregRename::IsProfitableToRename(VregRenameInfo *info) { if ((info->numInnerDefs == 0) && (info->numUses != info->numInnerUses)) { return true; @@ -326,11 +393,11 @@ bool VregRename::IsProfitableToRename(VregRenameInfo *info) { return false; } -void VregRename::RenameProfitableVreg(RegOperand *ropnd, const CGFuncLoops *loop) { +bool VregRename::RenameProfitableVreg(RegOperand *ropnd, const CGFuncLoops *loop) { regno_t vreg = ropnd->GetRegisterNumber(); VregRenameInfo *info = (vreg <= maxRegnoSeen) ? renameInfo[vreg] : nullptr; if ((info == nullptr) || loop->GetMultiEntries().size() || (IsProfitableToRename(info) == false)) { - return; + return false; } uint32 size = (ropnd->GetSize() == k64BitSize) ? k8ByteSize : k4ByteSize; @@ -392,6 +459,7 @@ void VregRename::RenameProfitableVreg(RegOperand *ropnd, const CGFuncLoops *loop } } } + return true; } void VregRename::RenameFindLoopVregs(const CGFuncLoops *loop) { @@ -429,11 +497,7 @@ void VregRename::RenameFindLoopVregs(const CGFuncLoops *loop) { void VregRename::UpdateVregInfo(regno_t vreg, BB *bb, bool isInner, bool isDef) { VregRenameInfo *info = renameInfo[vreg]; if (info == nullptr) { - info = memPool->New(); - renameInfo[vreg] = info; - if (vreg > maxRegnoSeen) { - maxRegnoSeen = vreg; - } + info = CreateVregRenameInfo(vreg); } if (isDef) { info->numDefs++; @@ -446,24 +510,29 @@ void VregRename::UpdateVregInfo(regno_t vreg, BB *bb, bool isInner, bool isDef) info->numInnerUses++; } } - if (info->firstBBLevelSeen) { - if (info->firstBBLevelSeen->GetInternalFlag2() > bb->GetInternalFlag2()) { + if (CGOptions::DoVregRenameBeforeRA()) { + if (info->firstBBLevelSeen) { + if (info->firstBBLevelSeen->GetInternalFlag2() > bb->GetInternalFlag2()) { + info->firstBBLevelSeen = bb; + } + } else { info->firstBBLevelSeen = bb; } - } else { - info->firstBBLevelSeen = bb; - } - if (info->lastBBLevelSeen) { - if (info->lastBBLevelSeen->GetInternalFlag2() < bb->GetInternalFlag2()) { + if (info->lastBBLevelSeen) { + if (info->lastBBLevelSeen->GetInternalFlag2() < bb->GetInternalFlag2()) { + info->lastBBLevelSeen = bb; + } + } else { info->lastBBLevelSeen = bb; } - } else { - info->lastBBLevelSeen = bb; } } void VregRename::RenameGetFuncVregInfo() { FOR_ALL_BB(bb, cgFunc) { + if (maxBBNum <= bb->GetId()) { + maxBBNum = bb->GetId() + 1; + } bool isInner = bb->GetLoop() ? bb->GetLoop()->GetInnerLoops().empty() : false; FOR_BB_INSNS(insn, bb) { if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { @@ -497,6 +566,336 @@ void VregRename::RenameGetFuncVregInfo() { } } +/* Use breadth first search to detect region */ +void VregRename::TraverseSwitchCase(std::queue &BBQueue, std::vector &visited, std::set &members) { + while (BBQueue.size()) { + BB *bb = BBQueue.front(); + BBQueue.pop(); + visited[bb->GetId()] = true; + members.insert(bb); + if (bb->GetKind() == BB::kBBGoto || bb->GetKind() == BB::kBBReturn) { + continue; + } + for (auto *succ : bb->GetSuccs()) { + if (visited[succ->GetId()]) { + continue; + } + bool predAllVisited = true; + for (auto *succPred : succ->GetPreds()) { + if (visited[succPred->GetId()] == false) { + predAllVisited = false; + break; + } + } + if (predAllVisited) { + BBQueue.push(succ); + } + } + } +} + +void VregRename::UpdateVregInfoForRegion(BB *headBB, regno_t vreg, bool isDef) { + SwitchVregInfo *info = (vreg <= maxRegnoSeen) ? caseRegInfo[vreg] : nullptr; + if (info == nullptr) { + info = CreateCaseVregInfo(vreg); + } + info->inRegion.insert(headBB); + if (isDef) { + if (info->regionHasDef.find(headBB->GetId()) == info->regionHasDef.end()) { + info->regionHasDef[headBB->GetId()] = 1; + } else { + info->regionHasDef[headBB->GetId()] ++; + } + } else { + if (info->regionHasUse.find(headBB->GetId()) == info->regionHasUse.end()) { + info->regionHasUse[headBB->GetId()] = 1; + } else { + info->regionHasUse[headBB->GetId()] ++; + } + } + info->globalCount++; +} + +void VregRename::RegionTraverseVreg(BB *headBB, std::set &members) { + CaseMemberInfo *cInfo = memPool->New(memPool); + cInfo->next = caseInfo; + caseInfo = cInfo; + cInfo->head = headBB; + for (auto *bb : members) { + cInfo->members.push_back(bb); + FOR_BB_INSNS(insn, bb) { + if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { + continue; + } + const AArch64MD *md = &AArch64CG::kMd[static_cast(*insn).GetMachineOpcode()]; + for (uint32 i = 0; i < insn->GetOperandSize(); ++i) { + Operand *opnd = &insn->GetOperand(i); + if (opnd->IsList()) { + /* call parameters */ + } else if (opnd->IsMemoryAccessOperand()) { + MemOperand *memopnd = static_cast(opnd); + RegOperand *base = static_cast(memopnd->GetBaseRegister()); + if (base != nullptr && base->IsVirtualRegister()) { + regno_t vreg = base->GetRegisterNumber(); + UpdateVregInfoForRegion(headBB, vreg, false); + } + RegOperand *offset = static_cast(memopnd->GetIndexRegister()); + if (offset != nullptr && offset->IsVirtualRegister()) { + regno_t vreg = offset->GetRegisterNumber(); + UpdateVregInfoForRegion(headBB, vreg, false); + } + } else if (opnd->IsRegister() && static_cast(opnd)->IsVirtualRegister() && + static_cast(opnd)->GetRegisterNumber() != ccRegno) { + bool isdef = static_cast(md->operand[i])->IsRegDef(); + regno_t vreg = static_cast(opnd)->GetRegisterNumber(); + UpdateVregInfoForRegion(headBB, vreg, isdef); + } + } + } + } +} + +/* This is called from coloring RA */ +void VregRename::RenameLoopAndSwitch(MapleVector &lrVec) { + if (CGOptions::DoLoopRename()) { + for (const auto *lp : cgFunc->GetLoops()) { + LoopRenameRegister(lp, lrVec); + } + } + if (CGOptions::DoSwitchRename()) { + SwitchRenameRegister(lrVec); + } +} + +void VregRename::FindInnerLoop(const CGFuncLoops *loop, MapleVector &lrVec) { + if (loop->GetInnerLoops().empty()) { + LoopRenameRegister(loop, lrVec); + return; + } + for (auto inner : loop->GetInnerLoops()) { + FindInnerLoop(inner, lrVec); + } +} + +void VregRename::LoopRenameRegister(const CGFuncLoops *loop, MapleVector &lrVec) { + for (auto *bb : loop->GetLoopMembers()) { + FOR_BB_INSNS(insn, bb) { + if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { + continue; + } + for (uint32 i = 0; i < insn->GetOperandSize(); ++i) { + Operand *opnd = &insn->GetOperand(i); + if (opnd->IsList()) { + /* call parameters */ + } else if (opnd->IsMemoryAccessOperand()) { + MemOperand *memopnd = static_cast(opnd); + RegOperand *base = static_cast(memopnd->GetBaseRegister()); + if (base != nullptr && base->IsVirtualRegister()) { + regno_t regno = base->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableVreg(base, loop)) { + lrVec[regno]->SetSpilled(false); + } + } + } + RegOperand *offset = static_cast(memopnd->GetIndexRegister()); + if (offset != nullptr && offset->IsVirtualRegister()) { + regno_t regno = offset->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableVreg(offset, loop)) { + lrVec[regno]->SetSpilled(false); + } + } + } + } else if (opnd->IsRegister() && static_cast(opnd)->IsVirtualRegister() && + static_cast(opnd)->GetRegisterNumber() != ccRegno) { + RegOperand *regOpnd = static_cast(opnd); + regno_t regno = regOpnd->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableVreg(regOpnd, loop)) { + lrVec[regno]->SetSpilled(false); + } + } + } + } + } + } +} + +void VregRename::SwitchRenameRegister(MapleVector &lrVec) { + for (CaseMemberInfo *info = caseInfo; info != nullptr; info = info->next) { + for (auto *bb : info->members) { + FOR_BB_INSNS(insn, bb) { + if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { + continue; + } + for (uint32 i = 0; i < insn->GetOperandSize(); ++i) { + Operand *opnd = &insn->GetOperand(i); + if (opnd->IsList()) { + /* call parameters */ + } else if (opnd->IsMemoryAccessOperand()) { + MemOperand *memopnd = static_cast(opnd); + RegOperand *base = static_cast(memopnd->GetBaseRegister()); + if (base != nullptr && base->IsVirtualRegister()) { + regno_t regno = base->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableSwitchVreg(base, info->head, info->members)) { + lrVec[regno]->SetSpilled(false); + } + } + } + RegOperand *offset = static_cast(memopnd->GetIndexRegister()); + if (offset != nullptr && offset->IsVirtualRegister()) { + regno_t regno = offset->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableSwitchVreg(offset, info->head, info->members)) { + lrVec[regno]->SetSpilled(false); + } + } + } + } else if (opnd->IsRegister() && static_cast(opnd)->IsVirtualRegister() && + static_cast(opnd)->GetRegisterNumber() != ccRegno) { + RegOperand *regOpnd = static_cast(opnd); + regno_t regno = regOpnd->GetRegisterNumber(); + if (regno < lrVec.size() && lrVec[regno]->IsSpilled()) { + if (RenameProfitableSwitchVreg(regOpnd, info->head, info->members)) { + lrVec[regno]->SetSpilled(false); + } + } + } + } + } + } + } +} + +void VregRename::RenameSwitchRegionReg(RegOperand *ropnd, BB *headBB, const MapleList &members) { + uint32 size = (ropnd->GetSize() == k64BitSize) ? k8ByteSize : k4ByteSize; + regno_t newRegno = cgFunc->NewVReg(ropnd->GetRegisterType(), size); + RegOperand *renameVreg = &cgFunc->CreateVirtualRegisterOperand(newRegno); + regno_t vreg = ropnd->GetRegisterNumber(); + for (auto bb : members) { + FOR_BB_INSNS(insn, bb) { + if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { + continue; + } + for (uint32 i = 0; i < insn->GetOperandSize(); ++i) { + Operand *opnd = &insn->GetOperand(i); + if (opnd->IsList()) { + /* call parameters */ + } else if (opnd->IsMemoryAccessOperand()) { + MemOperand *memopnd = static_cast(opnd); + RegOperand *base = static_cast(memopnd->GetBaseRegister()); + MemOperand *newMemOpnd = nullptr; + if (base != nullptr && base->IsVirtualRegister() && base->GetRegisterNumber() == vreg) { + newMemOpnd = static_cast(memopnd->Clone(*cgFunc->GetMemoryPool())); + newMemOpnd->SetBaseRegister(*renameVreg); + insn->SetOperand(i, *newMemOpnd); + } + RegOperand *offset = static_cast(memopnd->GetIndexRegister()); + if (offset != nullptr && offset->IsVirtualRegister() && offset->GetRegisterNumber() == vreg) { + if (newMemOpnd == nullptr) { + newMemOpnd = static_cast(memopnd->Clone(*cgFunc->GetMemoryPool())); + } + newMemOpnd->SetIndexRegister(*renameVreg); + insn->SetOperand(i, *newMemOpnd); + } + } else if (opnd->IsRegister() && static_cast(opnd)->IsVirtualRegister() && + static_cast(opnd)->GetRegisterNumber() == vreg) { + insn->SetOperand(i, *renameVreg); + } + } + } + } + /* delay insertion of rename move instruction after region finished renaming */ + MOperator mOp = (ropnd->GetRegisterType() == kRegTyInt) ? + ((size == k8BitSize) ? MOP_xmovrr : MOP_wmovrr) : + ((size == k8BitSize) ? MOP_xvmovd : MOP_xvmovs); + Insn &newInsn = static_cast(cgFunc)->GetCG()->BuildInstruction(mOp, *renameVreg, *ropnd); + Insn *first = headBB->GetFirstInsn(); + if (first) { + headBB->InsertInsnBefore(*first, newInsn); + } else { + headBB->AppendInsn(newInsn); + } +} + +bool VregRename::RenameProfitableSwitchVreg(RegOperand *ropnd, BB *headBB, const MapleList &members) { + regno_t vreg = ropnd->GetRegisterNumber(); + SwitchVregInfo *info = (vreg <= maxRegnoSeen) ? caseRegInfo[vreg] : nullptr; + if (info == nullptr || info->inRegion.size() < 2) { + return false; + } + uint32 defCnt = 0; + uint32 useCnt = 0; + for (auto *bb : info->inRegion) { + if (info->regionHasDef.find(bb->GetId()) != info->regionHasDef.end()) { + defCnt += info->regionHasDef[bb->GetId()]; + } + if (info->regionHasUse.find(bb->GetId()) != info->regionHasUse.end()) { + useCnt += info->regionHasUse[bb->GetId()]; + } + } + if (defCnt > 0/* || useCnt < 100*/) { + return false; + } + RenameSwitchRegionReg(ropnd, headBB, members); + return true; +} + +void VregRename::RegionFindVregForRename() { + //std::cout << "numCases " << numCases << "\n"; + for (CaseMemberInfo *info = caseInfo; info != nullptr; info = info->next) { + for (auto *bb : info->members) { + FOR_BB_INSNS(insn, bb) { + if (insn->IsImmaterialInsn() || !insn->IsMachineInstruction()) { + continue; + } + for (uint32 i = 0; i < insn->GetOperandSize(); ++i) { + Operand *opnd = &insn->GetOperand(i); + if (opnd->IsList()) { + /* call parameters */ + } else if (opnd->IsMemoryAccessOperand()) { + MemOperand *memopnd = static_cast(opnd); + RegOperand *base = static_cast(memopnd->GetBaseRegister()); + if (base != nullptr && base->IsVirtualRegister()) { + RenameProfitableSwitchVreg(base, info->head, info->members); + } + RegOperand *offset = static_cast(memopnd->GetIndexRegister()); + if (offset != nullptr && offset->IsVirtualRegister()) { + RenameProfitableSwitchVreg(offset, info->head, info->members); + } + } else if (opnd->IsRegister() && static_cast(opnd)->IsVirtualRegister() && + static_cast(opnd)->GetRegisterNumber() != ccRegno) { + RenameProfitableSwitchVreg(static_cast(opnd), info->head, info->members); + } + } + } + } + } +} + +void VregRename::DetectSwitchRegions() { + MIRLabelTable *labelTab = cgFunc->GetMirModule().CurFunction()->GetLabelTab(); + for (auto labels : labelTab->caseLabelSet) { + numCases++; + BB *bb = cgFunc->GetBBFromLab2BBMap(labels); + std::vector visited(maxBBNum, false); + std::set members; + std::queue BBQueue; + BBQueue.push(bb); + TraverseSwitchCase(BBQueue, visited, members); + RegionTraverseVreg(bb, members); + } + if (RENAME_DUMP) { + PrintSwitchRegion(); + PrintAllCaseRegInfo(); + } + if (CGOptions::DoVregRenameBeforeRA()) { + RegionFindVregForRename(); + } +} + void VregRename::RenameFindVregsToRename(const CGFuncLoops *loop) { if (loop->GetInnerLoops().empty()) { RenameFindLoopVregs(loop); @@ -507,14 +906,18 @@ void VregRename::RenameFindVregsToRename(const CGFuncLoops *loop) { } } - void VregRename::VregLongLiveRename() { - if (cgFunc->GetLoops().size() == 0) { - return; + if (CGOptions::DoLoopRename() || CGOptions::DoSwitchRename()) { + RenameGetFuncVregInfo(); } - RenameGetFuncVregInfo(); - for (const auto *lp : cgFunc->GetLoops()) { - RenameFindVregsToRename(lp); + if (cgFunc->GetLoops().size() != 0 && CGOptions::DoVregRenameBeforeRA() && CGOptions::DoLoopRename()) { + for (const auto *lp : cgFunc->GetLoops()) { + RenameFindVregsToRename(lp); + } + } + + if (CGOptions::DoSwitchRename()) { + DetectSwitchRegions(); } } @@ -522,7 +925,7 @@ void AArch64RaOpt::Run() { RaX0Opt x0Opt(cgFunc); x0Opt.PropagateX0(); - if (cgFunc->GetMirModule().GetSrcLang() == kSrcLangC && CGOptions::DoVregRename()) { + if (cgFunc->GetMirModule().GetSrcLang() == kSrcLangC && CGOptions::DoVregRenameBeforeRA()) { /* loop detection considers EH bb. That is not handled. So C only for now. */ LoopFinder *lf = memPool->New(*cgFunc, *memPool); lf->FormLoopHierarchy(); 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 01acfc23b4..6dd6f05389 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 @@ -566,6 +566,7 @@ bool CgRegAlloc::PhaseRun(maplebe::CGFunc &f) { dom = static_cast(it)->GetResult(); CHECK_FATAL(dom != nullptr, "null ptr check"); } + f.SetDoRename(true); while (success == false) { MemPool *phaseMp = GetPhaseMemPool(); LiveAnalysis *live = nullptr; diff --git a/src/mapleall/maple_be/src/cg/cg_option.cpp b/src/mapleall/maple_be/src/cg/cg_option.cpp index 3473adb1c7..a8894c9216 100644 --- a/src/mapleall/maple_be/src/cg/cg_option.cpp +++ b/src/mapleall/maple_be/src/cg/cg_option.cpp @@ -50,6 +50,7 @@ Range CGOptions::range = Range(); std::string CGOptions::fastFuncsAsmFile = ""; Range CGOptions::spillRanges = Range(); uint8 CGOptions::fastAllocMode = 0; /* 0: fast, 1: spill all */ +uint8 CGOptions::doVregRename = 0; bool CGOptions::fastAlloc = false; uint64 CGOptions::lsraBBOptSize = 150000; uint64 CGOptions::lsraInsnOptSize = 200000; @@ -65,7 +66,6 @@ bool CGOptions::doCFGO = false; bool CGOptions::doICO = false; bool CGOptions::doStoreLoadOpt = false; bool CGOptions::doGlobalOpt = false; -bool CGOptions::doVregRename = false; bool CGOptions::doMultiPassColorRA = true; bool CGOptions::doPrePeephole = false; bool CGOptions::doPeephole = false; @@ -430,8 +430,8 @@ const Descriptor kUsage[] = { "", "vreg-rename", kBuildTypeExperimental, - kArgCheckPolicyBool, - " --vreg-rename \tPerform rename of long live range around loops in coloring RA\n" + kArgCheckPolicyRequired, + " --vreg-rename=val \tPerform rename of long live range around loops in coloring RA\n" " --no-vreg-rename\n", "mplcg", {} }, @@ -1341,7 +1341,7 @@ bool CGOptions::SolveOptions(const std::vector