diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_color_ra.h b/src/mapleall/maple_be/include/cg/aarch64/aarch64_color_ra.h index 1d6954473c4d44ca5446735ee2e270f1826f222f..2e1fd6088e0072982ff1e83bcfc928abd723fda4 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_color_ra.h +++ b/src/mapleall/maple_be/include/cg/aarch64/aarch64_color_ra.h @@ -690,6 +690,14 @@ class LiveRange { fieldID = lr.fieldID; } + bool GetIsSpSave() const { + return isSpSave; + } + + void SetIsSpSave() { + isSpSave = true; + } + bool IsRematerializable(AArch64CGFunc &cgFunc, uint8 rematLev) const; std::vector Rematerialize(AArch64CGFunc *cgFunc, RegOperand ®Op); @@ -742,6 +750,7 @@ class LiveRange { } rematInfo; /* info for rematerializing value */ FieldID fieldID = 0; /* used only when op is OP_addrof or OP_dread */ bool addrUpper = false; /* indicates the upper bits of an addrof */ + bool isSpSave = false; /* contain SP in case of alloca */ }; /* One per bb, to communicate local usage to global RA */ @@ -1393,7 +1402,7 @@ class GraphColorRegAllocator : public RegAllocator { MemOperand *GetCommonReuseMem(const uint64 *conflict, const std::set &usedMemOpnd, uint32 size, RegType regType); MemOperand *GetReuseMem(uint32 vregNO, uint32 size, RegType regType); - MemOperand *GetSpillMem(uint32 vregNO, bool isDest, Insn &insn, AArch64reg regNO, bool &isOutOfRange) const; + MemOperand *GetSpillMem(uint32 vregNO, bool isDest, Insn &insn, AArch64reg regNO, bool &isOutOfRange); bool SetAvailableSpillReg(std::unordered_set &cannotUseReg, LiveRange &lr, uint64 &usedRegMask); void CollectCannotUseReg(std::unordered_set &cannotUseReg, const LiveRange &lr, Insn &insn); regno_t PickRegForSpill(uint64 &usedRegMask, RegType regType, uint32 spillIdx, bool &needSpillLr); @@ -1422,6 +1431,7 @@ class GraphColorRegAllocator : public RegAllocator { void GenerateSpillFillRegs(const Insn &insn); RegOperand *CreateSpillFillCode(const RegOperand &opnd, Insn &insn, uint32 spillCnt, bool isdef = false); bool SpillLiveRangeForSpills(); + void FinalizeSpSaveReg(); MapleVector::iterator GetHighPriorityLr(MapleVector &lrSet) const; void UpdateForbiddenForNeighbors(const LiveRange &lr) const; diff --git a/src/mapleall/maple_be/include/cg/cgfunc.h b/src/mapleall/maple_be/include/cg/cgfunc.h index 3beb2ddd914aa3c1ec6574c35645240bdced3bb7..0e66a610f2824caae20c75bdc90db669178f39cb 100644 --- a/src/mapleall/maple_be/include/cg/cgfunc.h +++ b/src/mapleall/maple_be/include/cg/cgfunc.h @@ -923,6 +923,14 @@ class CGFunc { lmbcTotalArgs = 0; } + void SetSpSaveReg(regno_t reg) { + spSaveReg = reg; + } + + regno_t GetSpSaveReg() { + return spSaveReg; + } + MapleVector &GetAllBBs() { return bbVec; } @@ -1276,14 +1284,15 @@ class CGFunc { #endif /* TARGARM32 */ MapleVector loops; MapleVector lmbcParamVec; + CGCFG *theCFG = nullptr; MapleSet scpIdSet; + const MapleString shortFuncName; int32 lmbcIntArgs = 0; int32 lmbcFpArgs = 0; uint32 lmbcTotalArgs = 0; - CGCFG *theCFG = nullptr; uint32 nextSpillLocation = 0; + regno_t spSaveReg = 0; - const MapleString shortFuncName; bool hasAsm = false; bool useFP = true; bool seenFP = true; diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp index 29ce220a612d7b587968e780c16099fbced04d8e..4906a5e6be097aa86503ddacd07be715eca12f26 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_args.cpp @@ -346,7 +346,13 @@ void AArch64MoveRegArgs::MoveRegisterArgs() { GenerateStrInsn(firstArgInfo, pairReg[firstIndex], numFpRegs[firstIndex], fpSize[firstIndex]); } - aarchCGFunc->GetFirstBB()->InsertAtBeginning(*aarchCGFunc->GetDummyBB()); + if (cgFunc->GetCG()->IsLmbc() && cgFunc->GetSpSaveReg()) { + /* lmbc uses vreg act as SP when alloca is present due to usage of FP for - offset */ + aarchCGFunc->GetFirstBB()->InsertAtEnd(*aarchCGFunc->GetDummyBB()); + } else { + /* Java requires insertion at begining as it has fast unwind and other features */ + aarchCGFunc->GetFirstBB()->InsertAtBeginning(*aarchCGFunc->GetDummyBB()); + } aarchCGFunc->SetCurBB(*formerCurBB); } @@ -476,7 +482,13 @@ void AArch64MoveRegArgs::MoveVRegisterArgs() const { } } - aarchCGFunc->GetFirstBB()->InsertAtBeginning(*aarchCGFunc->GetDummyBB()); + if (cgFunc->GetCG()->IsLmbc() && cgFunc->GetSpSaveReg()) { + /* lmbc uses vreg act as SP when alloca is present due to usage of FP for - offset */ + aarchCGFunc->GetFirstBB()->InsertAtEnd(*aarchCGFunc->GetDummyBB()); + } else { + /* Java requires insertion at begining as it has fast unwind and other features */ + aarchCGFunc->GetFirstBB()->InsertAtBeginning(*aarchCGFunc->GetDummyBB()); + } aarchCGFunc->SetCurBB(*formerCurBB); } } /* namespace maplebe */ diff --git a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 0feb263e57e69d8fe31c5093956a34d052888d68..35b3660930fc6f4792ff15409ca00b8ed91a6e26 100644 --- a/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/src/mapleall/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -6655,7 +6655,9 @@ void AArch64CGFunc::LmbcGenSaveSpForAlloca() { return; } Operand &spOpnd = GetOrCreatePhysicalRegisterOperand(RSP, k64BitSize, kRegTyInt); - RegOperand &spSaveOpnd = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, kSizeOfPtr)); + regno_t regno = NewVReg(kRegTyInt, kSizeOfPtr); + RegOperand &spSaveOpnd = CreateVirtualRegisterOperand(regno); + SetSpSaveReg(regno); Insn &save = GetCG()->BuildInstruction(MOP_xmovrr, spSaveOpnd, spOpnd); GetFirstBB()->AppendInsn(save); for (auto *retBB : GetExitBBsVec()) { 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 cbd182cbe3ff422be8ac50418e18f5503483d022..fa0dfed43760083a33be5ad2d7d8997287ba346f 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 @@ -15,6 +15,7 @@ #include "aarch64_color_ra.h" #include #include +#include #include "aarch64_cg.h" #include "mir_lower.h" #include "securec.h" @@ -454,9 +455,20 @@ void GraphColorRegAllocator::CalculatePriority(LiveRange &lr) const { uint32 numUses = 0; auto *a64CGFunc = static_cast(cgFunc); CG *cg = a64CGFunc->GetCG(); + bool isSpSave = false; if (cgFunc->GetCG()->IsLmbc()) { lr.SetRematLevel(kRematOff); + regno_t spSaveReg = cgFunc->GetSpSaveReg(); + if (spSaveReg && lr.GetRegNO() == spSaveReg) { + /* For lmbc, %fp and %sp are frame pointer and stack pointer respectively, unlike + * non-lmbc where %fp and %sp can be of the same. + * With alloca() potentially changing %sp, lmbc creates another register to act + * as %sp before alloca(). This register cannot be spilled as it is used to + * generate spill/fill instructions. + */ + isSpSave = true; + } } else { if (cg->GetRematLevel() >= kRematConst && lr.IsRematerializable(*a64CGFunc, kRematConst)) { lr.SetRematLevel(kRematConst); @@ -514,6 +526,10 @@ void GraphColorRegAllocator::CalculatePriority(LiveRange &lr) const { lr.SetPriority(pri); lr.SetNumDefs(numDefs); lr.SetNumUses(numUses); + if (isSpSave) { + lr.SetPriority(MAXFLOAT); + return; + } if (lr.GetPriority() > 0 && numDefs <= kPriorityDefThreashold && numUses <= kPriorityUseThreashold && cgFunc->NumBBs() > kPriorityBBThreashold && (static_cast(lr.GetNumBBMembers()) / cgFunc->NumBBs()) > kPriorityRatioThreashold) { @@ -2946,9 +2962,31 @@ MemOperand *GraphColorRegAllocator::GetReuseMem(uint32 vregNO, uint32 size, RegT } MemOperand *GraphColorRegAllocator::GetSpillMem(uint32 vregNO, bool isDest, Insn &insn, AArch64reg regNO, - bool &isOutOfRange) const { + bool &isOutOfRange) { auto *a64CGFunc = static_cast(cgFunc); MemOperand *memOpnd = a64CGFunc->GetOrCreatSpillMem(vregNO); + if (cgFunc->GetCG()->IsLmbc() && cgFunc->GetSpSaveReg()) { + LiveRange *lr = lrMap[cgFunc->GetSpSaveReg()]; + RegOperand *baseReg = nullptr; + if (lr == nullptr) { + BB *firstBB = cgFunc->GetFirstBB(); + FOR_BB_INSNS(bbInsn, firstBB) { + if (bbInsn->GetMachineOpcode() == MOP_xmovrr && bbInsn->GetOperand(kInsnSecondOpnd).IsRegister() && + static_cast(bbInsn->GetOperand(kInsnSecondOpnd)).GetRegisterNumber() == RSP) { + baseReg = static_cast(&bbInsn->GetOperand(kInsnFirstOpnd)); + CHECK_FATAL(baseReg->IsPhysicalRegister(), "Incorrect dest register for SP move"); + break; + } + } + CHECK_FATAL(baseReg, "Cannot find dest register for SP move"); + } else { + baseReg = &static_cast(cgFunc)->GetOrCreatePhysicalRegisterOperand( + static_cast(lr->GetAssignedRegNO()), k64BitSize, kRegTyInt); + } + MemOperand *newmemOpnd = (static_cast(memOpnd)->Clone(*cgFunc->GetMemoryPool())); + newmemOpnd->SetBaseRegister(*baseReg); + return (a64CGFunc->AdjustMemOperandIfOffsetOutOfRange(newmemOpnd, vregNO, isDest, insn, regNO, isOutOfRange)); + } return (a64CGFunc->AdjustMemOperandIfOffsetOutOfRange(memOpnd, vregNO, isDest, insn, regNO, isOutOfRange)); } @@ -4077,6 +4115,41 @@ bool GraphColorRegAllocator::SpillLiveRangeForSpills() { return done; } +void GraphColorRegAllocator::FinalizeSpSaveReg() { + if (!cgFunc->GetCG()->IsLmbc() || cgFunc->GetSpSaveReg() == 0) { + return; + } + LiveRange *lr = lrMap[cgFunc->GetSpSaveReg()]; + if (lr == nullptr) { + return; + } + RegOperand &preg = static_cast(cgFunc)->GetOrCreatePhysicalRegisterOperand( + static_cast(lr->GetAssignedRegNO()), k64BitSize, kRegTyInt); + BB *firstBB = cgFunc->GetFirstBB(); + FOR_BB_INSNS(insn, firstBB) { + if (insn->GetMachineOpcode() == MOP_xmovrr && insn->GetOperand(kInsnSecondOpnd).IsRegister() && + static_cast(insn->GetOperand(kInsnSecondOpnd)).GetRegisterNumber() == RSP) { + if (!static_cast(insn->GetOperand(kInsnFirstOpnd)).IsVirtualRegister()) { + break; + } + insn->SetOperand(kInsnFirstOpnd, preg); + break; + } + } + for (auto *retBB : cgFunc->GetExitBBsVec()) { + FOR_BB_INSNS(insn, retBB) { + if (insn->GetMachineOpcode() == MOP_xmovrr && + static_cast(insn->GetOperand(kInsnFirstOpnd)).GetRegisterNumber() == RSP) { + if (!static_cast(insn->GetOperand(kInsnSecondOpnd)).IsVirtualRegister()) { + break; + } + insn->SetOperand(kInsnSecondOpnd, preg); + break; + } + } + } +} + static bool ReloadAtCallee(CgOccur *occ) { auto *defOcc = occ->GetDef(); if (defOcc == nullptr || defOcc->GetOccType() != kOccStore) { @@ -4568,6 +4641,9 @@ void GraphColorRegAllocator::SplitVregAroundLoop(const CGFuncLoops &loop, const if (!AArch64Abi::IsCalleeSavedReg(static_cast(lr->GetAssignedRegNO()))) { continue; } + if (cgFunc->GetCG()->IsLmbc() && lr->GetIsSpSave()) { + continue; + } bool hasRef = false; for (auto *bb : loop.GetLoopMembers()) { LiveUnit *lu = lr->GetLiveUnitFromLuMap(bb->GetId()); @@ -4792,6 +4868,7 @@ void GraphColorRegAllocator::FinalizeRegisters() { } bool done = SpillLiveRangeForSpills(); if (done) { + FinalizeSpSaveReg(); 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 4fde7a8db1a3daa40e939951630862fc962d2009..381c026f96ad4608608825eda62c08ae4bd88e37 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 @@ -663,6 +663,9 @@ void ParamRegOpt::HandleParamReg() { if (movSrc.IsVirtualRegister()) { return; } + if (movSrc.IsPhysicalRegister() && movSrc.GetRegisterNumber() == RSP) { + return; + } TryToSplitParamReg(movDest, *insn); } }