diff --git a/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn b/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn index a98b991a53136225ca96b8d4a38f1c49fdb9418e..94b529d9165de70cdf9244b1e8e6d02b45349a1e 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn +++ b/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn @@ -145,6 +145,7 @@ src_libcgx86phases = [ "src/cg/reaching.cpp", "src/cg/local_opt.cpp", "src/cg/cfgo.cpp", + "src/cg/cg_dominance.cpp", ] src_libcgx8664 = [ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_abi.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_abi.h index a5cde3b09bb2b28f018b7ef0948ba96fb2613b19..aa6dda6b499cf46c810be151a98a1f9f6f31fbb0 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_abi.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_abi.h @@ -42,7 +42,6 @@ constexpr AArch64reg floatParmRegs[kNumFloatParmRegs] = {V0, V1, V2, V3, V4, V5, bool IsAvailableReg(AArch64reg reg); bool IsCalleeSavedReg(AArch64reg reg); bool IsCallerSaveReg(AArch64reg reg); -bool IsParamReg(AArch64reg reg); bool IsSpillReg(AArch64reg reg); bool IsExtraSpillReg(AArch64reg reg); bool IsSpillRegInRA(AArch64reg regNO, bool has3RegOpnd); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h index 97d8467fed541c1283b806ec2fd4a36e19f758c6..ce21e9f37b6fa2e50afeb4e0ea2251fa64606c39 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -113,7 +113,6 @@ public: void IntrinsifyCompareAndSwapInt(ListOperand &srcOpnds, PrimType pty); void IntrinsifyStringIndexOf(ListOperand &srcOpnds, const MIRSymbol &funcSym); void GenSaveMethodInfoCode(BB &bb) override; - void DetermineReturnTypeofCall() override; void HandleRCCall(bool begin, const MIRSymbol *retRef = nullptr) override; bool GenRetCleanup(const IntrinsiccallNode *cleanupNode, bool forEA = false); void HandleRetCleanup(NaryStmtNode &retNode) override; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_reg_info.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_reg_info.h index 3397cd806396d3e6ef0b2fc236374f1604c6f174..6b5e96c8a0bc009fd2e2592a4158a32eb205dc70 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_reg_info.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_reg_info.h @@ -28,45 +28,39 @@ public: ~AArch64RegInfo() override = default; - bool IsGPRegister(regno_t regNO) const override + // float 128-bit register has caller store, so pref alloced caller-save registers. + bool IsPrefCallerSaveRegs(RegType type, uint32 size) const override { - return AArch64isa::IsGPRegister(static_cast(regNO)); + return (type == kRegTyFloat && size == k128BitSize); } - /* phys reg which can be pre-Assignment */ - bool IsPreAssignedReg(regno_t regNO) const override + + // Additionally, only the bottom 64 bits of each value stored in virturl reg 8-15 need to be + // preserved 8; it is the responsibility of the caller to preserve larger values. + // Refer to Procedure Call Standard for the Arm 64-bit Architecture (AArch64) 2022Q3. $6.1.2 + bool IsCallerSavePartRegister(regno_t regNO, uint32 size) const override { - return AArch64Abi::IsParamReg(static_cast(regNO)); + return (regNO >= V8 && regNO <= V15) && size == k128BitSize; } + + bool IsGPRegister(regno_t regNO) const override + { + return AArch64isa::IsGPRegister(static_cast(regNO)); + } + regno_t GetIntRetReg(uint32 idx) override { - CHECK_FATAL(idx <= AArch64Abi::kNumIntParmRegs, "index out of range in IntRetReg"); + CHECK_FATAL(idx < AArch64Abi::kNumIntParmRegs, "index out of range in IntRetReg"); return AArch64Abi::intReturnRegs[idx]; } regno_t GetFpRetReg(uint32 idx) override { - CHECK_FATAL(idx <= AArch64Abi::kNumFloatParmRegs, "index out of range in IntRetReg"); + CHECK_FATAL(idx < AArch64Abi::kNumFloatParmRegs, "index out of range in IntRetReg"); return AArch64Abi::floatReturnRegs[idx]; } bool IsAvailableReg(regno_t regNO) const override { - /* special handle for R9 due to MRT_CallSlowNativeExt */ - if (regNO == R9 || regNO == R29) { - return false; - } return AArch64Abi::IsAvailableReg(static_cast(regNO)); } - /* Those registers can not be overwrite. */ - bool IsUntouchableReg(regno_t regNO) const override - { - if ((regNO == RSP) || (regNO == RFP) || regNO == RZR) { - return true; - } - /* when yieldpoint is enabled, the RYP(x19) can not be used. */ - if (GetCurrFunction()->GetCG()->GenYieldPoint() && (regNO == RYP)) { - return true; - } - return false; - } uint32 GetIntRegsParmsNum() override { return AArch64Abi::kNumIntParmRegs; @@ -131,18 +125,14 @@ public: void Init() override; void Fini() override; void SaveCalleeSavedReg(MapleSet savedRegs) override; - bool IsSpecialReg(regno_t regno) const override; bool IsCalleeSavedReg(regno_t regno) const override; bool IsYieldPointReg(regno_t regNO) const override; bool IsUnconcernedReg(regno_t regNO) const override; bool IsUnconcernedReg(const RegOperand ®Opnd) const override; bool IsSpillRegInRA(regno_t regNO, bool has3RegOpnd) override; RegOperand *GetOrCreatePhyRegOperand(regno_t regNO, uint32 size, RegType kind, uint32 flag = 0) override; - ListOperand *CreateListOperand() override; - Insn *BuildMovInstruction(Operand &opnd0, Operand &opnd1) override; Insn *BuildStrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) override; Insn *BuildLdrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) override; - Insn *BuildCommentInsn(const std::string &comment) override; MemOperand *GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize) override; MemOperand *AdjustMemOperandIfOffsetOutOfRange(MemOperand *memOpnd, regno_t vrNum, bool isDest, Insn &insn, regno_t regNum, bool &isOutOfRange) override; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_cfg.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_cfg.h index be00cefda10ed2cc4ba748b0ecda9bac53a4579e..a593c8709cd35d66609658da002a8c4dab4e3b8b 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_cfg.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_cfg.h @@ -127,6 +127,7 @@ private: static void MergeBB(BB &merger, BB &mergee); }; /* class CGCFG */ MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgHandleCFG, maplebe::CGFunc) +OVERRIDE_DEPENDENCE MAPLE_FUNC_PHASE_DECLARE_END } /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h index b382a4d1e3d7d64b8c3bbec8a36a81c8b18bfdce..4f6461fc63757d55c27c6b7ee42e9ba81f9ccee1 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h @@ -71,6 +71,8 @@ namespace maplebe { class CGFuncLoops; class CGFunc; +using BBID = uint32; + class BB { public: enum BBKind : uint8 { @@ -85,7 +87,7 @@ public: kBBLast }; - BB(uint32 bbID, MapleAllocator &mallocator) + BB(BBID bbID, MapleAllocator &mallocator) : id(bbID), kind(kBBFallthru), /* kBBFallthru default kind */ labIdx(MIRLabelTable::GetDummyLabel()), @@ -1021,12 +1023,14 @@ public: : AnalysisResult(&memPool), cgfunc(&cgFunc), alloc(&memPool), + cycleSuccs(alloc.Adapter()), visitedBBs(alloc.Adapter()), sortedBBs(alloc.Adapter()) { } ~Bfs() = default; + void SeekCycles(); bool AllPredBBVisited(const BB &bb, long &level) const; BB *MarkStraightLineBBInBFS(BB *bb); BB *SearchForStraightLineBBs(BB &bb); @@ -1035,6 +1039,7 @@ public: CGFunc *cgfunc; MapleAllocator alloc; + MapleVector> cycleSuccs; // bb's succs in cycle MapleVector visitedBBs; MapleVector sortedBBs; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h index 14d4956cf2cbdc8d073249253485247012108e80..abe2f00a69162233fdd21818b5d55edb49b70662 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h @@ -23,7 +23,6 @@ #include "reg_info.h" #include "cgbb.h" #include "call_conv.h" -#include "reg_alloc.h" #include "cfi.h" #include "dbg.h" #include "reaching.h" @@ -200,7 +199,6 @@ public: void DumpLoop() const; void ClearLoopInfo(); Operand *HandleExpr(const BaseNode &parent, BaseNode &expr); - virtual void DetermineReturnTypeofCall() = 0; /* handle rc reset */ virtual void HandleRCCall(bool begin, const MIRSymbol *retRef = nullptr) = 0; virtual void HandleRetCleanup(NaryStmtNode &retNode) = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h index ec142c0feedda5ab4abe9cddc6ba7109514749b7..15a55536caca4cf875eead1b84b468abb2f39667 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h @@ -38,11 +38,6 @@ class DepNode; struct InsnDesc; class Insn { public: - enum RetType : uint8 { - kRegNull, /* no return type */ - kRegFloat, /* return register is V0 */ - kRegInt /* return register is R0 */ - }; /* MCC_DecRefResetPair clear 2 stack position, MCC_ClearLocalStackRef clear 1 stack position */ static constexpr uint8 kMaxStackOffsetSize = 2; @@ -521,16 +516,6 @@ public: return !isCallReturnUnsigned; } - void SetRetType(RetType retType) - { - this->retType = retType; - } - - RetType GetRetType() const - { - return retType; - } - void SetClearStackOffset(short index, int64 offset) { CHECK_FATAL(index < kMaxStackOffsetSize, "out of clearStackOffset's range"); @@ -698,7 +683,6 @@ private: uint32 id = 0; uint32 address = 0; uint32 nopNum = 0; - RetType retType = kRegNull; /* if this insn is call, it represent the return register type R0/V0 */ uint32 retSize = 0; /* Byte size of the return value if insn is a call. */ /* record the stack cleared by MCC_ClearLocalStackRef or MCC_DecRefResetPair */ int64 clearStackOffset[kMaxStackOffsetSize] = {-1, -1}; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc.h index ac5045bfa02e4ecc30cbea6a2c9647fd3b32bba0..c2ad76c389ca8f5650f57f0ffce1a86815c71616 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc.h @@ -16,61 +16,74 @@ #ifndef MAPLEBE_INCLUDE_CG_REG_ALLOC_H #define MAPLEBE_INCLUDE_CG_REG_ALLOC_H -#include -#include -#include "isa.h" -#include "cg_phase.h" +#include "cgfunc.h" #include "maple_phase_manager.h" namespace maplebe { -class VirtualRegNode { +class RATimerManager { public: - VirtualRegNode() = default; + RATimerManager(const RATimerManager&) = delete; + RATimerManager& operator=(const RATimerManager&) = delete; - VirtualRegNode(RegType type, uint32 size) : regType(type), size(size), regNO(kInvalidRegNO) {} - - virtual ~VirtualRegNode() = default; - - void AssignPhysicalRegister(regno_t phyRegNO) - { - regNO = phyRegNO; - } - - RegType GetType() const + static MPLTimerManager &GetInstance() { - return regType; + static RATimerManager raTimerM{}; + return raTimerM.timerM; } - uint32 GetSize() const + void PrintAllTimerAndClear(const std::string &funcName) { - return size; + LogInfo::MapleLogger() << "Func[" << funcName << "] Reg Alloc Time:\n"; + LogInfo::MapleLogger() << timerM.ConvertAllTimer2Str() << std::endl; + timerM.Clear(); } - private: - RegType regType = kRegTyUndef; - uint32 size = 0; /* size in bytes */ - regno_t regNO = kInvalidRegNO; /* physical register assigned by register allocation */ + RATimerManager() = default; + ~RATimerManager() = default; + + MPLTimerManager timerM; }; +// RA time statistics marco. If defined, RA time consumed will print. +#ifdef REG_ALLOC_TIME_STATISTICS +#define RA_TIMER_REGISTER(timerName, str) MPLTimerRegister timerName##Timer(RATimerManager::GetInstance(), str) +#define RA_TIMER_STOP(timerName) timerName##Timer.Stop() +#define RA_TIMER_PRINT(funcName) RATimerManager::GetInstance().PrintAllTimerAndClear(funcName) +#else +#define RA_TIMER_REGISTER(name, str) +#define RA_TIMER_STOP(name) +#define RA_TIMER_PRINT(funcName) +#endif + class RegAllocator { public: - RegAllocator(CGFunc &tempCGFunc, MemPool &memPool) : cgFunc(&tempCGFunc), memPool(&memPool), alloc(&memPool) {} + RegAllocator(CGFunc &tempCGFunc, MemPool &memPool) + : cgFunc(&tempCGFunc), + memPool(&memPool), + alloc(&memPool), + regInfo(tempCGFunc.GetTargetRegInfo()) + { + regInfo->Init(); + } virtual ~RegAllocator() = default; virtual bool AllocateRegisters() = 0; - bool IsYieldPointReg(regno_t regNO) const; - bool IsUntouchableReg(regno_t regNO) const; + virtual std::string PhaseName() const + { + return "regalloc"; + } void SetNeedDump(bool dump) { needDump = dump; } protected: - CGFunc *cgFunc; - MemPool *memPool; + CGFunc *cgFunc = nullptr; + MemPool *memPool = nullptr; MapleAllocator alloc; + RegisterInfo *regInfo = nullptr; bool needDump = false; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_basic.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_basic.h index 9f5fb98072f6ae07cbbfb6d9a912f44fd0e4d42f..7568d1038d2848c86361a0202c73ed0029e3c650 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_basic.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_basic.h @@ -33,7 +33,6 @@ public: regLiveness(alloc.Adapter()), rememberRegs(alloc.Adapter()) { - regInfo = cgFunc.GetTargetRegInfo(); availRegSet.resize(regInfo->GetAllRegNum()); } @@ -54,7 +53,6 @@ public: void AllocHandleDest(Insn &insn, Operand &opnd, uint32 idx); void AllocHandleSrcList(Insn &insn, Operand &opnd, uint32 idx); void AllocHandleSrc(Insn &insn, Operand &opnd, uint32 idx); - bool IsSpecialReg(regno_t reg) const; void SaveCalleeSavedReg(const RegOperand &opnd); protected: @@ -69,8 +67,7 @@ protected: void SetupRegLiveness(MemOperand &opnd, uint32 insnId); void SetupRegLiveness(ListOperand &opnd, uint32 insnId, bool isDef); void SetupRegLiveness(RegOperand &opnd, uint32 insnId, bool isDef); - - RegisterInfo *regInfo = nullptr; + MapleSet calleeSaveUsed; MapleVector availRegSet; MapleMap regMap; /* virtual-register-to-physical-register map */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h index b0e711c8f862496730f94bb0c01a2442f5cf20ee..f705e83100f64c457caccc24d3008c61e476485b 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h @@ -675,18 +675,16 @@ class LSRALinearScanRegAllocator : public RegAllocator { } } localDefLiveIn.resize(callerSaves.size()); - localDefLiveOut.resize(callerSaves.size()); + localDefAfterInsn.resize(callerSaves.size()); } void Run(); private: - using LocalDefBBSet = std::unordered_set; - bool firstTime = true; Bfs *bfs = nullptr; std::vector callerSaves; - std::vector localDefLiveIn; - std::vector localDefLiveOut; + std::vector> localDefLiveIn; // bbid: which is defined in livein + std::vector> localDefAfterInsn; // bbid: def-insnid bool UpdateLocalDefWithBBLiveIn(const BB &bb); void CollectCallerNoNeedReloadByInsn(const Insn &insn); @@ -716,8 +714,6 @@ public: moveInfoVec(alloc.Adapter()), dereivedRef2Base(alloc.Adapter()) { - regInfo = cgFunc.GetTargetRegInfo(); - regInfo->Init(); for (uint32 i = 0; i < regInfo->GetIntRegs().size(); ++i) { intParamQueue.push_back(initialQue); } @@ -730,7 +726,6 @@ public: ~LSRALinearScanRegAllocator() override = default; bool AllocateRegisters() override; - void PreWork(); bool CheckForReg(Operand &opnd, const Insn &insn, const LiveInterval &li, regno_t regNO, bool isDef) const; void PrintRegSet(const MapleSet &set, const std::string &str) const; void PrintLiveInterval(const LiveInterval &li, const std::string &str) const; @@ -745,7 +740,6 @@ public: void PrintLiveIntervals() const; void DebugCheckActiveList() const; void InitFreeRegPool(); - void RecordCall(Insn &insn); void RecordPhysRegs(const RegOperand ®Opnd, uint32 insnNum, bool isDef); void UpdateLiveIntervalState(const BB &bb, LiveInterval &li) const; void UpdateRegUsedInfo(LiveInterval &li, regno_t regNO); @@ -763,41 +757,23 @@ public: void UpdateParamAllocateInfo(const LiveInterval &li); void RetireActive(LiveInterval &li, uint32 insnID); void AssignPhysRegsForLi(LiveInterval &li); - LiveInterval *GetLiveIntervalAt(uint32 regNO, uint32 pos); - bool OpndNeedAllocation(const Insn &insn, Operand &opnd, bool isDef, uint32 insnNum); - void InsertParamToActive(Operand &opnd); - void InsertToActive(Operand &opnd, uint32 insnNum); - void ReleasePregToSet(const LiveInterval &li, uint32 preg); - void UpdateActiveAtRetirement(uint32 insnID); - void RetireFromActive(const Insn &insn); - void AssignPhysRegsForInsn(Insn &insn); RegOperand *GetReplaceOpnd(Insn &insn, Operand &opnd, uint32 &spillIdx, bool isDef); RegOperand *GetReplaceUdOpnd(Insn &insn, Operand &opnd, uint32 &spillIdx); - void ResolveSplitBBEdge(BB &bb); void SetAllocMode(); void LinearScanRegAllocator(); void FinalizeRegisters(); - void ResolveMoveVec(); void CollectReferenceMap(); void SolveRegOpndDeoptInfo(const RegOperand ®Opnd, DeoptInfo &deoptInfo, int32 deoptVregNO) const; void SolveMemOpndDeoptInfo(const MemOperand &memOpnd, DeoptInfo &deoptInfo, int32 deoptVregNO) const; void CollectDeoptInfo(); void SpillOperand(Insn &insn, Operand &opnd, bool isDef, uint32 spillIdx); - void SetOperandSpill(Operand &opnd); regno_t HandleSpillForLi(LiveInterval &li); - RegOperand *HandleSpillForInsn(const Insn &insn, Operand &opnd); MemOperand *GetSpillMem(uint32 vregNO, bool isDest, Insn &insn, regno_t regNO, bool &isOutOfRange, uint32 bitSize) const; void InsertCallerSave(Insn &insn, Operand &opnd, bool isDef); uint32 GetRegFromMask(uint32 mask, regno_t offset, const LiveInterval &li); - uint32 GetSpecialPhysRegPattern(const LiveInterval &li); - uint32 GetRegFromSet(MapleSet &set, regno_t offset, LiveInterval &li, regno_t forcedReg = 0) const; - uint32 AssignSpecialPhysRegPattern(const Insn &insn, LiveInterval &li); uint32 FindAvailablePhyReg(LiveInterval &li); uint32 AssignPhysRegs(LiveInterval &li); - void SetupIntervalRangesByOperand(Operand &opnd, const Insn &insn, uint32 blockFrom, bool isDef); - bool SplitLiveInterval(LiveInterval &li, uint32 pos); - void LiveIntervalQueueInsert(LiveInterval &li); void ComputeLoopLiveIntervalPriority(const CGFuncLoops &loop); void ComputeLoopLiveIntervalPriorityInInsn(const Insn &insn); void SetLiSpill(LiveInterval &li); @@ -805,9 +781,9 @@ public: private: uint32 FindAvailablePhyRegByFastAlloc(LiveInterval &li); bool NeedSaveAcrossCall(LiveInterval &li); + uint32 FindAvailablePhyRegAcrossCall(LiveInterval &li, bool isIntReg); uint32 FindAvailablePhyReg(LiveInterval &li, bool isIntReg); - RegisterInfo *regInfo = nullptr; regno_t firstIntReg = 0; regno_t firstFpReg = 0; @@ -852,7 +828,6 @@ private: bool fastAlloc = false; bool spillAll = false; bool needExtraSpillReg = false; - bool isSpillZero = false; uint64 spillCount = 0; uint64 reloadCount = 0; uint64 callerSaveSpillCount = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_info.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_info.h index f194b796792f68c9c6393fbea9f77e1411491a26..72391660ece1cf26085ce00aa53a0bce64d07615 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_info.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_info.h @@ -16,12 +16,38 @@ #ifndef MAPLEBE_INCLUDE_CG_REG_INFO_H #define MAPLEBE_INCLUDE_CG_REG_INFO_H -#include -#include #include "isa.h" #include "insn.h" namespace maplebe { +class VirtualRegNode { +public: + VirtualRegNode() = default; + + VirtualRegNode(RegType type, uint32 size) : regType(type), size(size), regNO(kInvalidRegNO) {} + + virtual ~VirtualRegNode() = default; + + void AssignPhysicalRegister(regno_t phyRegNO) + { + regNO = phyRegNO; + } + + RegType GetType() const + { + return regType; + } + + uint32 GetSize() const + { + return size; + } + +private: + RegType regType = kRegTyUndef; + uint32 size = 0; /* size in bytes */ + regno_t regNO = kInvalidRegNO; /* physical register assigned by register allocation */ +}; class RegisterInfo { public: @@ -69,18 +95,24 @@ public: { return cgFunc; } + // When some registers are allocated to the callee, the caller stores a part of the registers + // and the callee stores another part of the registers. + // For these registers, it is a better choice to assign them as caller-save registers. + virtual bool IsPrefCallerSaveRegs(RegType type, uint32 size) const + { + return false; + } + virtual bool IsCallerSavePartRegister(regno_t regNO, uint32 size) const + { + return false; + } virtual RegOperand *GetOrCreatePhyRegOperand(regno_t regNO, uint32 size, RegType kind, uint32 flag = 0) = 0; - virtual ListOperand *CreateListOperand() = 0; - virtual Insn *BuildMovInstruction(Operand &opnd0, Operand &opnd1) = 0; virtual bool IsGPRegister(regno_t regNO) const = 0; - virtual bool IsPreAssignedReg(regno_t regNO) const = 0; virtual uint32 GetIntParamRegIdx(regno_t regNO) const = 0; virtual uint32 GetFpParamRegIdx(regno_t regNO) const = 0; - virtual bool IsSpecialReg(regno_t regno) const = 0; virtual bool IsAvailableReg(regno_t regNO) const = 0; virtual bool IsCalleeSavedReg(regno_t regno) const = 0; virtual bool IsYieldPointReg(regno_t regNO) const = 0; - virtual bool IsUntouchableReg(uint32 regNO) const = 0; virtual bool IsUnconcernedReg(regno_t regNO) const = 0; virtual bool IsUnconcernedReg(const RegOperand ®Opnd) const = 0; virtual bool IsVirtualRegister(const RegOperand ®Opnd) = 0; @@ -102,7 +134,6 @@ public: virtual bool IsSpillRegInRA(regno_t regNO, bool has3RegOpnd) = 0; virtual Insn *BuildStrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) = 0; virtual Insn *BuildLdrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) = 0; - virtual Insn *BuildCommentInsn(const std::string &comment) = 0; virtual MemOperand *GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize) = 0; virtual MemOperand *AdjustMemOperandIfOffsetOutOfRange(MemOperand *memOpnd, regno_t vrNum, bool isDest, Insn &insn, regno_t regNum, bool &isOutOfRange) = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h index 8d0402093eeed24c38d44c14a7813c6d587d8efd..7ef95db6163f8bd68c18130557b0f20c6b35a6a5 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h @@ -47,7 +47,6 @@ public: void AssignLmbcFormalParams() override; void LmbcGenSaveSpForAlloca() override; void MergeReturn() override; - void DetermineReturnTypeofCall() override; void HandleRCCall(bool begin, const MIRSymbol *retRef = nullptr) override; void HandleRetCleanup(NaryStmtNode &retNode) override; void SelectDassign(DassignNode &stmt, Operand &opnd0) override; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def index be78d6ebd253f5bf799949405aa43f8bfef66f33..9ed22c5e71df6a0e7e0e4fc787c80ff046f948e2 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_md.def @@ -68,7 +68,6 @@ DEFINE_MOP(MOP_movfd_r_m, {&OpndDesc::Reg128FS,&OpndDesc::Mem128D},ISSTORE,kLtAl /* movabs */ //The movabs instruction to load arbitrary 64-bit constant into register and to load/store integer register from/to arbitrary constant 64-bit address is available DEFINE_MOP(MOP_movabs_i_r, {&OpndDesc::Imm64,&OpndDesc::Reg64ID},ISMOVE,kLtAlu,"movabs","0,1",1) -DEFINE_MOP(MOP_movabs_s_r, {&OpndDesc::StImm64,&OpndDesc::Reg64ID},ISMOVE,kLtAlu,"movabs","0,1",1) DEFINE_MOP(MOP_movabs_l_r, {&OpndDesc::Lbl64,&OpndDesc::Reg64ID},ISMOVE,kLtAlu,"movabs","0,1",1) /* push & pop & lea */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_reg_info.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_reg_info.h index 017a4962b87df96d2cbd6f9d9d85045398bda4f2..a5b08f9ef92014d2f2ba1d4d53b0bf6b22cee90f 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_reg_info.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_reg_info.h @@ -33,17 +33,13 @@ public: void Init() override; void Fini() override; void SaveCalleeSavedReg(MapleSet savedRegs) override; - bool IsSpecialReg(regno_t regno) const override; bool IsCalleeSavedReg(regno_t regno) const override; bool IsYieldPointReg(regno_t regNO) const override; bool IsUnconcernedReg(regno_t regNO) const override; bool IsUnconcernedReg(const RegOperand ®Opnd) const override; RegOperand *GetOrCreatePhyRegOperand(regno_t regNO, uint32 size, RegType kind, uint32 flag) override; - ListOperand *CreateListOperand() override; - Insn *BuildMovInstruction(Operand &opnd0, Operand &opnd1) override; Insn *BuildStrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) override; Insn *BuildLdrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) override; - Insn *BuildCommentInsn(const std::string &comment) override; void FreeSpillRegMem(regno_t vrNum) override; MemOperand *GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize) override; MemOperand *AdjustMemOperandIfOffsetOutOfRange(MemOperand *memOpnd, regno_t vrNum, bool isDest, Insn &insn, @@ -52,11 +48,6 @@ public: { return x64::IsGPRegister(static_cast(regNO)); } - /* Those registers can not be overwrite. */ - bool IsUntouchableReg(regno_t regNO) const override - { - return false; - } /* Refactor later: Integrate parameters and return Reg */ uint32 GetIntRegsParmsNum() override { @@ -89,16 +80,6 @@ public: CHECK_FATAL(idx <= GetFpRetRegsNum(), "index out of range in IntRetReg"); return static_cast(X64CallConvImpl::GetCallConvInfo(callConv).GetFloatReturnRegs()[idx]); } - /* phys reg which can be pre-Assignment: - * INT param regs -- rdi, rsi, rdx, rcx, r8, r9 - * INT return regs -- rdx, rax - * FP param regs -- xmm0 ~ xmm7 - * FP return regs -- xmm0 ~ xmm1 - */ - bool IsPreAssignedReg(regno_t regNO) const override - { - return x64::IsParamReg(static_cast(regNO)) || regNO == x64::RAX || regNO == x64::RDX; - } uint32 GetIntParamRegIdx(regno_t regNO) const override { CHECK_FATAL(GetIntRegs().size(), "should be init before"); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_abi.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_abi.cpp index d902bcfabb2f9451b63eaa2b12b556d932225616..1d7ab897237bd4c7a3e27579b488d37531c8f41d 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_abi.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_abi.cpp @@ -78,32 +78,6 @@ bool IsCalleeSavedReg(AArch64reg reg) } } -bool IsParamReg(AArch64reg reg) -{ - switch (reg) { -/* integer registers */ -#define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \ - case R##ID: { \ - return isParam; \ - } -#define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64) -#include "aarch64_int_regs.def" -#undef INT_REG -#undef INT_REG_ALIAS -/* fp-simd registers */ -#define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \ - case V##ID: { \ - return isParam; \ - } -#define FP_SIMD_REG_ALIAS(ID) -#include "aarch64_fp_simd_regs.def" -#undef FP_SIMD_REG -#undef FP_SIMD_REG_ALIAS - default: - return false; - } -} - bool IsSpillReg(AArch64reg reg) { switch (reg) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 2166f8555a09f43de72a29e06836398680a2c57d..d40889b1dd6740255d83f386803ab4db7a783dfe 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -1213,9 +1213,7 @@ void AArch64CGFunc::SelectAsm(AsmNode &node) SetHasAsm(); if (Globals::GetInstance()->GetOptimLevel() > CGOptions::kLevel0) { if (GetCG()->GetCGOptions().DoLinearScanRegisterAllocation()) { - LogInfo::MapleLogger() << "Using coloring RA\n"; - const_cast(GetCG()->GetCGOptions()).SetOption(CGOptions::kDoColorRegAlloc); - const_cast(GetCG()->GetCGOptions()).ClearOption(CGOptions::kDoLinearScanRegAlloc); + CHECK_FATAL(false, "NIY, lsra unsupported inline asm!"); } } Operand *asmString = &CreateStringOperand(node.asmString); @@ -7502,47 +7500,6 @@ RegOperand &AArch64CGFunc::GetOrCreateVirtualRegisterOperand(RegOperand ®Opnd } } -/* - * Traverse all call insn to determine return type of it - * If the following insn is mov/str/blr and use R0/V0, it means the call insn have reture value - */ -void AArch64CGFunc::DetermineReturnTypeofCall() -{ - FOR_ALL_BB(bb, this) { - if (bb->IsUnreachable() || !bb->HasCall()) { - continue; - } - FOR_BB_INSNS(insn, bb) { - if (!insn->IsTargetInsn()) { - continue; - } - if (!insn->IsCall() || insn->GetMachineOpcode() == MOP_asm) { - continue; - } - Insn *nextInsn = insn->GetNextMachineInsn(); - if (nextInsn == nullptr) { - continue; - } - if ((nextInsn->GetMachineOpcode() != MOP_asm) && - ((nextInsn->IsMove() && nextInsn->GetOperand(kInsnSecondOpnd).IsRegister()) || nextInsn->IsStore() || - (nextInsn->IsCall() && nextInsn->GetOperand(kInsnFirstOpnd).IsRegister()))) { - auto *srcOpnd = static_cast(&nextInsn->GetOperand(kInsnFirstOpnd)); - CHECK_FATAL(srcOpnd != nullptr, "nullptr"); - if (!srcOpnd->IsPhysicalRegister()) { - continue; - } - if (srcOpnd->GetRegisterNumber() == R0) { - insn->SetRetType(Insn::kRegInt); - continue; - } - if (srcOpnd->GetRegisterNumber() == V0) { - insn->SetRetType(Insn::kRegFloat); - } - } - } - } -} - void AArch64CGFunc::HandleRCCall(bool begin, const MIRSymbol *retRef) { if (!GetCG()->GenLocalRC() && !begin) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_reg_info.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_reg_info.cpp index f36d982d6f8a69d5409038ddab0eb43cd661efb6..9a534b885efa6d1ab9f3c61234a0ef9cad16dcf5 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_reg_info.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_reg_info.cpp @@ -27,8 +27,7 @@ void AArch64RegInfo::Init() if (IsYieldPointReg(regNO)) { continue; } - if (regNO == R29 && !GetCurrFunction()->UseFP()) { - AddToAllRegs(regNO); + if (regNO == R29 && GetCurrFunction()->UseFP()) { continue; } if (!AArch64Abi::IsAvailableReg(static_cast(regNO))) { @@ -60,20 +59,6 @@ void AArch64RegInfo::SaveCalleeSavedReg(MapleSet savedRegs) } } -bool AArch64RegInfo::IsSpecialReg(regno_t regno) const -{ - AArch64reg reg = static_cast(regno); - if ((reg == RLR) || (reg == RSP)) { - return true; - } - - /* when yieldpoint is enabled, the dedicated register can not be allocated. */ - if (IsYieldPointReg(reg)) { - return true; - } - - return false; -} bool AArch64RegInfo::IsSpillRegInRA(regno_t regNO, bool has3RegOpnd) { return AArch64Abi::IsSpillRegInRA(static_cast(regNO), has3RegOpnd); @@ -85,7 +70,7 @@ bool AArch64RegInfo::IsCalleeSavedReg(regno_t regno) const bool AArch64RegInfo::IsYieldPointReg(regno_t regno) const { /* when yieldpoint is enabled, x19 is reserved. */ - if (GetCurrFunction()->GetCG()->GenYieldPoint()) { + if (CGOptions::GetInstance().GenYieldPoint()) { return (static_cast(regno) == RYP); } return false; @@ -93,7 +78,7 @@ bool AArch64RegInfo::IsYieldPointReg(regno_t regno) const bool AArch64RegInfo::IsUnconcernedReg(regno_t regNO) const { /* RFP = 32, RLR = 31, RSP = 33, RZR = 34, ccReg */ - if ((regNO >= RLR && regNO <= RZR) || regNO == RFP) { + if ((regNO >= RLR && regNO <= RZR) || regNO == RFP || regNO == kRFLAG) { return true; } @@ -123,21 +108,6 @@ RegOperand *AArch64RegInfo::GetOrCreatePhyRegOperand(regno_t regNO, uint32 size, return &aarch64CgFunc->GetOrCreatePhysicalRegisterOperand(static_cast(regNO), size, kind, flag); } -ListOperand *AArch64RegInfo::CreateListOperand() -{ - AArch64CGFunc *aarch64CgFunc = static_cast(GetCurrFunction()); - return (aarch64CgFunc->CreateListOpnd(*aarch64CgFunc->GetFuncScopeAllocator())); -} - -Insn *AArch64RegInfo::BuildMovInstruction(Operand &opnd0, Operand &opnd1) -{ - AArch64CGFunc *a64CGFunc = static_cast(GetCurrFunction()); - MOperator mop = - a64CGFunc->PickMovInsn(static_cast(opnd0), static_cast(opnd1)); - Insn *newInsn = &a64CGFunc->GetInsnBuilder()->BuildInsn(mop, opnd0, opnd1); - return newInsn; -} - Insn *AArch64RegInfo::BuildStrInsn(uint32 regSize, PrimType stype, RegOperand &phyOpnd, MemOperand &memOpnd) { AArch64CGFunc *a64CGFunc = static_cast(GetCurrFunction()); @@ -150,15 +120,10 @@ Insn *AArch64RegInfo::BuildLdrInsn(uint32 regSize, PrimType stype, RegOperand &p return &a64CGFunc->GetInsnBuilder()->BuildInsn(a64CGFunc->PickLdInsn(regSize, stype), phyOpnd, memOpnd); } -Insn *AArch64RegInfo::BuildCommentInsn(const std::string &comment) -{ - return &(static_cast(GetCurrFunction())->CreateCommentInsn("split around loop begin")); -} - MemOperand *AArch64RegInfo::GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize) { AArch64CGFunc *a64CGFunc = static_cast(GetCurrFunction()); - return a64CGFunc->GetOrCreatSpillMem(vrNum); + return a64CGFunc->GetOrCreatSpillMem(vrNum, bitSize); } MemOperand *AArch64RegInfo::AdjustMemOperandIfOffsetOutOfRange(MemOperand *memOpnd, regno_t vrNum, bool isDest, Insn &insn, regno_t regNum, bool &isOutOfRange) diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp index cfde4a458746f6134130471019f6411fdd6851e3..668f5a27cfdde50f48e168cd02b8af49e3b09dec 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp @@ -521,6 +521,7 @@ void CGCFG::RemoveBB(BB &curBB, bool isGotoIf) if (curBB.GetNext()->GetLabIdx() == 0) { targetLabel = insnVisitor->GetCGFunc()->CreateLabel(); curBB.GetNext()->SetLabIdx(targetLabel); + cgFunc->SetLab2BBMap(targetLabel, *curBB.GetNext()); } else { targetLabel = curBB.GetNext()->GetLabIdx(); } @@ -925,10 +926,16 @@ void CGCFG::BreakCriticalEdge(BB &pred, BB &succ) } #endif +void CgHandleCFG::GetAnalysisDependence(AnalysisDep &aDep) const +{ + aDep.SetPreservedAll(); +} + bool CgHandleCFG::PhaseRun(maplebe::CGFunc &f) { CGCFG *cfg = f.GetMemoryPool()->New(f); f.SetTheCFG(cfg); + cfg->MarkLabelTakenBB(); /* build control flow graph */ f.GetTheCFG()->BuildCFG(); /* analysis unreachable code */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_option.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_option.cpp index 411f964aefa161aa677f9b0733f4f43f9d883cb1..b0f6da7e4d4ba953193ee7d335ee113aaf3fb7c3 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_option.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_option.cpp @@ -796,6 +796,8 @@ void CGOptions::EnableLiteCG() ClearOption(kConstFold); ClearOption(kProEpilogueOpt); ClearOption(kTailCallOpt); + ClearOption(kDoColorRegAlloc); + SetOption(kDoLinearScanRegAlloc); } void CGOptions::SetTargetMachine(const std::string &str) diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgbb.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgbb.cpp index 9a05f13aa9df44a18acac75fb510be60c0959ffa..e1b90545d5a9ffe5ec73817177436467ff41bf9b 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgbb.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgbb.cpp @@ -15,7 +15,6 @@ #include "cgbb.h" #include "cgfunc.h" -#include "loop.h" namespace maplebe { constexpr uint32 kCondBrNum = 2; @@ -370,33 +369,77 @@ BB *BB::GetValidPrev() return pre; } +void Bfs::SeekCycles() +{ + MapleVector visited(cgfunc->NumBBs(), false, alloc.Adapter()); + MapleVector onPath(cgfunc->NumBBs(), false, alloc.Adapter()); + MapleStack workStack(alloc.Adapter()); + + // searching for succsBB in the same cycle as BB + auto seekCycleSuccs = [this, &visited, &onPath, &workStack](const BB &bb, const MapleList succs) { + for (auto *succBB : succs) { + if (!visited[succBB->GetId()]) { + workStack.push(succBB); + } else { + if (onPath[succBB->GetId()]) { + (void)cycleSuccs[bb.GetId()].insert(succBB->GetId()); + } + } + } + }; + + // searhing workStack BBs cycle + auto seekCycles = [&visited, &onPath, &workStack, &seekCycleSuccs]() { + while (!workStack.empty()) { + auto *bb = workStack.top(); + if (visited[bb->GetId()]) { + onPath[bb->GetId()] = false; + workStack.pop(); + continue; + } + + visited[bb->GetId()] = true; + onPath[bb->GetId()] = true; + seekCycleSuccs(*bb, bb->GetSuccs()); + seekCycleSuccs(*bb, bb->GetEhSuccs()); + } + }; + + bool changed = false; + do { + changed = false; + FOR_ALL_BB(bb, cgfunc) { + if (!visited[bb->GetId()]) { + workStack.push(bb); + seekCycles(); + changed = true; + } + } + } while (changed); +} + bool Bfs::AllPredBBVisited(const BB &bb, long &level) const { - bool isAllPredsVisited = true; - for (const auto *predBB : bb.GetPreds()) { - /* See if pred bb is a loop back edge */ - bool isBackEdge = false; - for (const auto *loopBB : predBB->GetLoopSuccs()) { - if (loopBB == &bb) { - isBackEdge = true; - break; + // check pred bb is in cycle + auto predBBInCycle = [this](const BB &bb, const BB &predBB) { + for (auto bbId : cycleSuccs[predBB.GetId()]) { + if (bb.GetId() == bbId) { + return true; } } - if (!isBackEdge && !visitedBBs[predBB->GetId()]) { + return false; + }; + + bool isAllPredsVisited = true; + for (const auto *predBB : bb.GetPreds()) { + if (!predBBInCycle(bb, *predBB) && !visitedBBs[predBB->GetId()]) { isAllPredsVisited = false; break; } level = std::max(level, predBB->GetInternalFlag2()); } for (const auto *predEhBB : bb.GetEhPreds()) { - bool isBackEdge = false; - for (const auto *loopBB : predEhBB->GetLoopSuccs()) { - if (loopBB == &bb) { - isBackEdge = true; - break; - } - } - if (!isBackEdge && !visitedBBs[predEhBB->GetId()]) { + if (!predBBInCycle(bb, *predEhBB) && !visitedBBs[predEhBB->GetId()]) { isAllPredsVisited = false; break; } @@ -500,22 +543,22 @@ void Bfs::BFS(BB &curBB) void Bfs::ComputeBlockOrder() { - visitedBBs.clear(); + cycleSuccs.assign(cgfunc->NumBBs(), MapleSet(alloc.Adapter())); + SeekCycles(); + sortedBBs.clear(); - visitedBBs.resize(cgfunc->NumBBs()); - for (uint32 i = 0; i < cgfunc->NumBBs(); ++i) { - visitedBBs[i] = false; - } + visitedBBs.assign(cgfunc->NumBBs(), false); BB *cleanupBB = nullptr; FOR_ALL_BB(bb, cgfunc) { bb->SetInternalFlag1(0); bb->SetInternalFlag2(1); - if (bb->GetFirstStmt() == cgfunc->GetCleanupLabel()) { + if (bb->IsCleanup()) { + DEBUG_ASSERT(cleanupBB == nullptr, "one cleanupBB in the function only"); cleanupBB = bb; } } - for (BB *bb = cleanupBB; bb != nullptr; bb = bb->GetNext()) { - bb->SetInternalFlag1(1); + if (cleanupBB != nullptr) { + cleanupBB->SetInternalFlag1(1); } bool changed; @@ -524,7 +567,7 @@ void Bfs::ComputeBlockOrder() do { changed = false; FOR_ALL_BB(bb, cgfunc) { - if (bb->GetInternalFlag1() == 1) { + if (bb->GetInternalFlag1() == 1 || bb->IsUnreachable()) { continue; } if (visitedBBs[bb->GetId()]) { @@ -542,22 +585,22 @@ void Bfs::ComputeBlockOrder() if (!done) { done = true; } else { - LogInfo::MapleLogger() << "Error: RA BFS loop " << sortedCnt << " in func " << cgfunc->GetName() - << "\n"; + LogInfo::MapleLogger() << "Error: RA BFS loop " << sortedCnt + << " in func " << cgfunc->GetName() << "\n"; + CHECK_FATAL(false, ""); } } sortedCnt = sortedBBs.size(); } while (changed); - for (BB *bb = cleanupBB; bb != nullptr; bb = bb->GetNext()) { - sortedBBs.push_back(bb); + if (cleanupBB != nullptr) { + sortedBBs.push_back(cleanupBB); } } void CgBBSort::GetAnalysisDependence(AnalysisDep &aDep) const { aDep.AddRequired(); - aDep.AddRequired(); aDep.SetPreservedAll(); } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp index e7ae4eb258769da896153b853f983730fda99c2f..d06d4c3512b0adde69e52e6e6b721ec5486ce610 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp @@ -2263,6 +2263,9 @@ void CGFunc::ProcessExitBBVec() void CGFunc::AddCommonExitBB() { + if (commonExitBB != nullptr) { + return; + } uint32 i = 0; while (exitBBVec[i]->IsUnreachable() && i < exitBBVec.size()) { i++; @@ -2322,7 +2325,6 @@ void CGFunc::HandleFunction() MarkCatchBBs(); } MarkCleanupEntryBB(); - DetermineReturnTypeofCall(); theCFG->MarkLabelTakenBB(); theCFG->UnreachCodeAnalysis(); EraseUnreachableStackMapInsns(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp index 049dc22493f9306b7e8b91b85ca9ab00652c5d37..9d9f4555d0cc013728ec8fb0d485f34107543aa1 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp @@ -267,8 +267,12 @@ void Insn::Check() const /* check if the type of each operand matches */ for (uint32 i = 0; i < insnOperandSize; ++i) { Operand &opnd = GetOperand(i); - if (opnd.GetKind() != md->GetOpndDes(i)->GetOperandType()) { - CHECK_FATAL(false, " operand type does not match machine description "); + auto *opndDesc = md->GetOpndDes(i); + if (opnd.IsImmediate()) { + CHECK_FATAL(opndDesc->IsImm(), "operand type does not match machine description!"); + } else { + CHECK_FATAL(opnd.GetKind() == opndDesc->GetOperandType(), + "operand type does not match machine description!"); } } } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc.cpp index 672ada0f9fb46d188c7e278069e8d2472670af6a..68122fad0a325dc9190f9ba301a0ddffbd008e7e 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc.cpp @@ -31,72 +31,70 @@ namespace maplebe { void CgRegAlloc::GetAnalysisDependence(AnalysisDep &aDep) const { - if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevelLiteCG || - CGOptions::GetInstance().DoLinearScanRegisterAllocation()) { - aDep.AddRequired(); - } - if (Globals::GetInstance()->GetOptimLevel() > CGOptions::kLevel0) { - aDep.AddRequired(); - aDep.AddRequired(); - aDep.PreservedAllExcept(); + if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) { + return; } -#if TARGAARCH64 - if (Globals::GetInstance()->GetOptimLevel() > CGOptions::kLevel0 && - CGOptions::GetInstance().DoColoringBasedRegisterAllocation()) { + + if (CGOptions::GetInstance().DoLinearScanRegisterAllocation()) { + aDep.AddRequired(); + } else if (CGOptions::GetInstance().DoColoringBasedRegisterAllocation()) { aDep.AddRequired(); } -#endif + + aDep.AddRequired(); + aDep.AddRequired(); + aDep.PreservedAllExcept(); } bool CgRegAlloc::PhaseRun(maplebe::CGFunc &f) { bool success = false; - while (success == false) { + while (!success) { MemPool *phaseMp = GetPhaseMemPool(); + LiveAnalysis *live = nullptr; + /* create register allocator */ RegAllocator *regAllocator = nullptr; + MemPool *tempMP = memPoolCtrler.NewMemPool("regalloc", true); if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevel0) { regAllocator = phaseMp->New(f, *phaseMp); - } else if (Globals::GetInstance()->GetOptimLevel() == CGOptions::kLevelLiteCG) { + } else if (f.GetCG()->GetCGOptions().DoLinearScanRegisterAllocation()) { Bfs *bfs = GET_ANALYSIS(CgBBSort, f); CHECK_FATAL(bfs != nullptr, "null ptr check"); + live = GET_ANALYSIS(CgLiveAnalysis, f); + CHECK_FATAL(live != nullptr, "null ptr check"); + // revert liveanalysis result container. + live->ResetLiveSet(); regAllocator = phaseMp->New(f, *phaseMp, bfs); - } else { #if TARGAARCH64 - if (f.GetCG()->GetCGOptions().DoLinearScanRegisterAllocation()) { - Bfs *bfs = GET_ANALYSIS(CgBBSort, f); - CHECK_FATAL(bfs != nullptr, "null ptr check"); - regAllocator = phaseMp->New(f, *phaseMp, bfs); - } else if (f.GetCG()->GetCGOptions().DoColoringBasedRegisterAllocation()) { - MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( - &CgLiveAnalysis::id, f); - LiveAnalysis *live = static_cast(it)->GetResult(); - CHECK_FATAL(live != nullptr, "null ptr check"); - /* revert liveanalysis result container. */ - live->ResetLiveSet(); - DomAnalysis *dom = GET_ANALYSIS(CgDomAnalysis, f); - CHECK_FATAL(dom != nullptr, "null ptr check"); - regAllocator = phaseMp->New(f, *phaseMp, *dom); - } else { - maple::LogInfo::MapleLogger(kLlErr) - << "Warning: We only support Linear Scan and GraphColor register allocation\n"; - } -#elif TARGX86_64 - LogInfo::MapleLogger(kLlErr) << "Error: We only support -O0, and -LiteCG for x64.\n"; + } else if (f.GetCG()->GetCGOptions().DoColoringBasedRegisterAllocation()) { + MaplePhase *it = GetAnalysisInfoHook()->ForceRunAnalysisPhase, CGFunc>( + &CgLiveAnalysis::id, f); + live = static_cast(it)->GetResult(); + CHECK_FATAL(live != nullptr, "null ptr check"); + /* revert liveanalysis result container. */ + live->ResetLiveSet(); + DomAnalysis *dom = GET_ANALYSIS(CgDomAnalysis, f); + CHECK_FATAL(dom != nullptr, "null ptr check"); + regAllocator = phaseMp->New(f, *tempMP, *dom); #endif + } else { + maple::LogInfo::MapleLogger(kLlErr) + << "Warning: We only support Linear Scan and GraphColor register allocation\n"; } + RA_TIMER_REGISTER(ra, "RA Time"); /* do register allocation */ CHECK_FATAL(regAllocator != nullptr, "regAllocator is null in CgDoRegAlloc::Run"); regAllocator->SetNeedDump(RA_DUMP); f.SetIsAfterRegAlloc(); success = regAllocator->AllocateRegisters(); + if (Globals::GetInstance()->GetOptimLevel() > CGOptions::kLevel0) { GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLiveAnalysis::id); } + memPoolCtrler.DeleteMemPool(tempMP); } - if (Globals::GetInstance()->GetOptimLevel() > CGOptions::kLevel0) { - GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLoopAnalysis::id); - } + RA_TIMER_PRINT(f.GetName()); return false; } -} /* namespace maplebe */ \ No newline at end of file +} /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_basic.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_basic.cpp index 4b47f0a3c185deefcb797cf540a5f877015db624..6ecb23ae72ae59e72ad2ad2d9e2c7fd7976257aa 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_basic.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_basic.cpp @@ -162,12 +162,6 @@ void DefaultO0RegAllocator::InitAvailReg() } } -/* these registers can not be allocated */ -bool DefaultO0RegAllocator::IsSpecialReg(regno_t reg) const -{ - return regInfo->IsSpecialReg(reg); -} - void DefaultO0RegAllocator::ReleaseReg(const RegOperand ®Opnd) { ReleaseReg(regMap[regOpnd.GetRegisterNumber()]); @@ -177,7 +171,8 @@ void DefaultO0RegAllocator::ReleaseReg(regno_t reg) { DEBUG_ASSERT(reg < regInfo->GetAllRegNum(), "can't release virtual register"); liveReg.erase(reg); - if (!IsSpecialReg(reg)) { + /* Special registers can not be allocated */ + if (!regInfo->IsUnconcernedReg(reg)) { availRegSet[reg] = true; } } @@ -429,7 +424,6 @@ void DefaultO0RegAllocator::AllocHandleSrc(Insn &insn, Operand &opnd, uint32 idx bool DefaultO0RegAllocator::AllocateRegisters() { - regInfo->Init(); InitAvailReg(); cgFunc->SetIsAfterRegAlloc(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp index c64434cee1f97be93065658812f0e1cde151fe9e..1b11149fad23c1b459e75a9bb368a24594a90f66 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp @@ -14,17 +14,10 @@ */ #include "reg_alloc_lsra.h" -#include -#include -#include #include "loop.h" +#include namespace maplebe { -/* - * ================== - * = Linear Scan RA - * ================== - */ namespace { constexpr uint32 kSpilled = 1; constexpr uint32 kMinLiveIntervalLength = 20; @@ -33,33 +26,6 @@ constexpr uint32 kPrintedActiveListLength = 10; constexpr uint32 kLoopWeight = 4; } // namespace -#define IN_SPILL_RANGE \ - (cgFunc->GetName().find(CGOptions::GetDumpFunc()) != std::string::npos && ++debugSpillCnt && \ - (CGOptions::GetSpillRangesBegin() < debugSpillCnt) && (debugSpillCnt < CGOptions::GetSpillRangesEnd())) - -#ifdef RA_PERF_ANALYSIS -static long bfsUS = 0; -static long liveIntervalUS = 0; -static long holesUS = 0; -static long lsraUS = 0; -static long finalizeUS = 0; -static long totalUS = 0; - -extern void printLSRATime() -{ - std::cout << "============================================================\n"; - std::cout << " LSRA sub-phase time information \n"; - std::cout << "============================================================\n"; - std::cout << "BFS BB sorting cost: " << bfsUS << "us \n"; - std::cout << "live interval computing cost: " << liveIntervalUS << "us \n"; - std::cout << "live range approximation cost: " << holesUS << "us \n"; - std::cout << "LSRA cost: " << lsraUS << "us \n"; - std::cout << "finalize cost: " << finalizeUS << "us \n"; - std::cout << "LSRA total cost: " << totalUS << "us \n"; - std::cout << "============================================================\n"; -} -#endif - /* * This LSRA implementation is an interpretation of the [Poletto97] paper. * BFS BB ordering is used to order the instructions. The live intervals are vased on @@ -106,7 +72,8 @@ void LSRALinearScanRegAllocator::PrintLiveRanges(const LiveInterval &li) const { if (li.GetAssignedReg() != 0) { uint32 base = (li.GetRegType() == kRegTyInt) ? firstIntReg : firstFpReg; - LogInfo::MapleLogger() << "(assigned R" << (li.GetAssignedReg() - base) << ")"; + char regType = (li.GetRegType() == kRegTyInt) ? 'R' : 'V'; + LogInfo::MapleLogger() << "(assigned " << regType << (li.GetAssignedReg() - base) << ")"; } if (li.GetStackSlot() == kSpilled) { LogInfo::MapleLogger() << "(spill)"; @@ -254,6 +221,7 @@ void LSRALinearScanRegAllocator::PrintLiveRangesGraph() const void LSRALinearScanRegAllocator::SpillStackMapInfo() { + RA_TIMER_REGISTER(lsra, "LSRA SpillStackMapInfo"); const auto &referenceMapInsns = cgFunc->GetStackMapInsns(); for (auto *insn : referenceMapInsns) { @@ -309,15 +277,15 @@ void LSRALinearScanRegAllocator::PrintLiveInterval(const LiveInterval &li, const if (li.GetIsCall() != nullptr) { LogInfo::MapleLogger() << " firstDef " << li.GetFirstDef(); LogInfo::MapleLogger() << " isCall"; - } else if (li.GetPhysUse()) { + } else if (li.GetPhysUse() > 0) { LogInfo::MapleLogger() << "\tregNO " << li.GetRegNO(); LogInfo::MapleLogger() << " firstDef " << li.GetFirstDef(); LogInfo::MapleLogger() << " physUse " << li.GetPhysUse(); LogInfo::MapleLogger() << " endByCall " << li.IsEndByCall(); } else { - LogInfo::MapleLogger() << "\tregNO " << std::setw(5) << li.GetRegNO(); /* show regno with 5 width */ - LogInfo::MapleLogger() << " firstDef " << std::setw(8) << li.GetFirstDef(); /* show firstDef with 8 width */ - LogInfo::MapleLogger() << " lastUse " << std::setw(8) << li.GetLastUse(); /* show lastUse with 8 width */ + LogInfo::MapleLogger() << "\tregNO " << li.GetRegNO(); + LogInfo::MapleLogger() << " firstDef " << li.GetFirstDef(); + LogInfo::MapleLogger() << " lastUse " << li.GetLastUse(); LogInfo::MapleLogger() << " assigned " << li.GetAssignedReg(); LogInfo::MapleLogger() << " refCount " << li.GetRefCount(); LogInfo::MapleLogger() << " priority " << li.GetPriority(); @@ -373,7 +341,7 @@ void LSRALinearScanRegAllocator::PrintActiveListSimple() const for (const auto *li : active) { uint32 assignedReg = li->GetAssignedReg(); LogInfo::MapleLogger() << li->GetRegNO() << "(" << assignedReg << ", "; - if (li->GetPhysUse()) { + if (li->GetPhysUse() > 0) { LogInfo::MapleLogger() << "p) "; } else { LogInfo::MapleLogger() << li->GetFirstAcrossedCall(); @@ -442,7 +410,7 @@ void LSRALinearScanRegAllocator::DebugCheckActiveList() const */ void LSRALinearScanRegAllocator::InitFreeRegPool() { - for (regno_t regNO = regInfo->GetInvalidReg(); regNO < regInfo->GetAllRegNum(); ++regNO) { + for (regno_t regNO : regInfo->GetAllRegs()) { if (!regInfo->IsAvailableReg(regNO)) { continue; } @@ -517,10 +485,7 @@ void LSRALinearScanRegAllocator::RecordPhysRegs(const RegOperand ®Opnd, uint3 if (regType == kRegTyCc || regType == kRegTyVary) { return; } - if (regInfo->IsUntouchableReg(regNO)) { - return; - } - if (!regInfo->IsPreAssignedReg(regNO)) { + if (regInfo->IsUnconcernedReg(regNO) || regInfo->IsVirtualRegister(regNO)) { return; } if (isDef) { @@ -561,7 +526,7 @@ void LSRALinearScanRegAllocator::UpdateLiveIntervalState(const BB &bb, LiveInter li.SetNotInCatchState(); } - if (bb.GetInternalFlag1()) { + if (bb.GetInternalFlag1() != 0) { li.SetInCleanupState(); } else { li.SetNotInCleanupState(bb.GetId() == 1); @@ -593,7 +558,7 @@ void LSRALinearScanRegAllocator::SetupLiveInterval(Operand &opnd, Insn &insn, bo } auto ®Opnd = static_cast(opnd); uint32 insnNum = insn.GetId(); - if (regOpnd.IsPhysicalRegister()) { + if (!regInfo->IsVirtualRegister(regOpnd)) { RecordPhysRegs(regOpnd, insnNum, isDef); return; } @@ -719,30 +684,6 @@ MapleVector::iterator LSRALinearScanReg return rangeFinder; } -void LSRALinearScanRegAllocator::SetupIntervalRangesByOperand(Operand &opnd, const Insn &insn, uint32 blockFrom, - bool isDef) -{ - auto ®Opnd = static_cast(opnd); - RegType regType = regOpnd.GetRegisterType(); - if (regType == kRegTyCc || regType == kRegTyVary) { - return; - } - regno_t regNO = regOpnd.GetRegisterNumber(); - if (regNO <= regInfo->GetAllRegNum()) { - return; - } - if (!isDef) { - liveIntervalsArray[regNO]->AddRange(blockFrom, insn.GetId()); - return; - } - if (liveIntervalsArray[regNO]->GetRanges().empty()) { - liveIntervalsArray[regNO]->AddRange(insn.GetId(), insn.GetId()); - } else { - liveIntervalsArray[regNO]->GetRanges().front().SetStart(insn.GetId()); - } - liveIntervalsArray[regNO]->AddUsePositions(insn.GetId()); -} - /* Extend live interval with live-in info */ void LSRALinearScanRegAllocator::UpdateLiveIntervalByLiveIn(const BB &bb, uint32 insnNum) { @@ -794,8 +735,8 @@ void LSRALinearScanRegAllocator::UpdateLiveIntervalByLiveIn(const BB &bb, uint32 /* traverse live in regNO, for each live in regNO create a new liveinterval */ void LSRALinearScanRegAllocator::UpdateParamLiveIntervalByLiveIn(const BB &bb, uint32 insnNum) { - for (const auto ®NO : bb.GetLiveInRegNO()) { - if (!regInfo->IsPreAssignedReg(regNO)) { + for (const auto regNO : bb.GetLiveInRegNO()) { + if (regInfo->IsUnconcernedReg(regNO) || regInfo->IsVirtualRegister(regNO)) { continue; } auto *li = memPool->New(*memPool); @@ -857,8 +798,11 @@ void LSRALinearScanRegAllocator::ComputeLiveOut(BB &bb, uint32 insnNum) * for each live out regNO if the last corresponding live interval is created within this bb * update this lastUse of li to the end of BB */ - for (const auto ®NO : bb.GetLiveOutRegNO()) { - if (regInfo->IsPreAssignedReg(static_cast(regNO))) { + for (const auto regNO : bb.GetLiveOutRegNO()) { + if (regInfo->IsUnconcernedReg(regNO)) { + continue; + } + if (!regInfo->IsVirtualRegister(regNO)) { LiveInterval *liOut = nullptr; if (regInfo->IsGPRegister(regNO)) { if (intParamQueue[regInfo->GetIntParamRegIdx(regNO)].empty()) { @@ -897,45 +841,62 @@ void LSRALinearScanRegAllocator::ComputeLiveOut(BB &bb, uint32 insnNum) } } +struct RegOpndInfo { + RegOpndInfo(RegOperand &opnd, uint32 size, uint32 idx, bool def) + : regOpnd(opnd), regSize(size), opndIdx(idx), isDef(def) {} + RegOperand ®Opnd; + uint32 regSize = 0; + uint32 opndIdx = -1; + bool isDef = false; +}; + void LSRALinearScanRegAllocator::ComputeLiveIntervalForEachOperand(Insn &insn) { - uint32 numUses = 0; + std::vector allRegOpndInfo; const InsnDesc *md = insn.GetDesc(); - uint32 opndNum = insn.GetOperandSize(); - /* - * we need to process src opnd first just in case the src/dest vreg are the same and the src vreg belongs to the - * last interval. - */ - for (int32 i = opndNum - 1; i >= 0; --i) { - Operand &opnd = insn.GetOperand(static_cast(i)); + for (uint32 i = 0; i < insn.GetOperandSize(); ++i) { + Operand &opnd = insn.GetOperand(i); const OpndDesc *opndDesc = md->GetOpndDes(i); DEBUG_ASSERT(opndDesc != nullptr, "ptr null check."); if (opnd.IsRegister()) { auto ®Opnd = static_cast(opnd); - /* Specifically, the "use-def" opnd is treated as a "use" opnd */ + // Specifically, the "use-def" opnd is treated as a "use" opnd bool isUse = opndDesc->IsRegUse(); - /* Fixup: The size in the insn md of x64 is not accurate, and the size in the fload opnd - does not change, so we use the size in the opnd first. */ + // Fixup: The size in the insn md of x64 is not accurate, and the size in the fload opnd + // does not change, so we use the size in the opnd first. auto regSize = (regOpnd.GetRegisterType() == kRegTyInt ? opndDesc->GetSize() : regOpnd.GetSize()); - SetupLiveInterval(opnd, insn, !isUse, numUses, regSize); + allRegOpndInfo.emplace_back(regOpnd, regSize, i, !isUse); } else if (opnd.IsMemoryAccessOperand()) { - bool isDef = false; - auto &memOpnd = static_cast(opnd); - Operand *base = memOpnd.GetBaseRegister(); - Operand *offset = memOpnd.GetIndexRegister(); + auto &memOpnd = static_cast(opnd); + RegOperand *base = memOpnd.GetBaseRegister(); + RegOperand *offset = memOpnd.GetIndexRegister(); if (base != nullptr) { - SetupLiveInterval(*base, insn, isDef, numUses, k64BitSize); + allRegOpndInfo.emplace_back(*base, k64BitSize, i, false); } if (offset != nullptr) { - SetupLiveInterval(*offset, insn, isDef, numUses, k64BitSize); + allRegOpndInfo.emplace_back(*offset, k64BitSize, i, false); } } else if (opnd.IsList()) { - auto &listOpnd = static_cast(opnd); + auto &listOpnd = static_cast(opnd); for (auto op : listOpnd.GetOperands()) { - SetupLiveInterval(*op, insn, opndDesc->IsDef(), numUses, opnd.GetSize()); + allRegOpndInfo.emplace_back(*op, op->GetSize(), i, opndDesc->IsDef()); } } } + + uint32 numUses = 0; + for (auto ®OpndInfo : allRegOpndInfo) { + if (!regOpndInfo.isDef) { + SetupLiveInterval(regOpndInfo.regOpnd, insn, false, numUses, regOpndInfo.regSize); + } + } + + for (auto ®OpndInfo : allRegOpndInfo) { + if (regOpndInfo.isDef) { + SetupLiveInterval(regOpndInfo.regOpnd, insn, true, numUses, regOpndInfo.regSize); + } + } + if (numUses >= regInfo->GetNormalUseOperandNum()) { needExtraSpillReg = true; } @@ -967,7 +928,7 @@ void LSRALinearScanRegAllocator::ComputeLoopLiveIntervalPriorityInInsn(const Ins continue; } auto ®Opnd = static_cast(opnd); - if (regOpnd.IsPhysicalRegister()) { + if (!regInfo->IsVirtualRegister(regOpnd)) { continue; } uint32 regNo = regOpnd.GetRegisterNumber(); @@ -983,6 +944,7 @@ void LSRALinearScanRegAllocator::ComputeLoopLiveIntervalPriorityInInsn(const Ins void LSRALinearScanRegAllocator::ComputeLiveInterval() { + RA_TIMER_REGISTER(lsra, "LSRA ComputeLiveInterval"); liQue.clear(); uint32 regUsedInBBSz = (cgFunc->GetMaxVReg() / (sizeof(uint64) * k8ByteSize) + 1); regUsedInBB.resize(regUsedInBBSz, 0); @@ -1011,17 +973,15 @@ void LSRALinearScanRegAllocator::ComputeLiveInterval() * and then their live begins. * next optimization, you can determine which registers are actually used. */ - RegOperand *retReg = nullptr; - if (insn->GetRetType() == Insn::kRegInt) { for (uint32 i = 0; i < regInfo->GetIntRetRegsNum(); i++) { - retReg = regInfo->GetOrCreatePhyRegOperand(regInfo->GetIntRetReg(i), k64BitSize, kRegTyInt); + auto *retReg = regInfo->GetOrCreatePhyRegOperand(regInfo->GetIntRetReg(i), + k64BitSize, kRegTyInt); RecordPhysRegs(*retReg, insnNum, true); } - } else { for (uint32 i = 0; i < regInfo->GetFpRetRegsNum(); i++) { - retReg = regInfo->GetOrCreatePhyRegOperand(regInfo->GetFpRetReg(i), k64BitSize, kRegTyFloat); + auto *retReg = regInfo->GetOrCreatePhyRegOperand(regInfo->GetFpRetReg(i), + k64BitSize, kRegTyFloat); RecordPhysRegs(*retReg, insnNum, true); - } } } ++insnNum; @@ -1037,7 +997,7 @@ void LSRALinearScanRegAllocator::ComputeLiveInterval() if (li == nullptr || li->GetRegNO() == 0) { continue; } - if (li->GetIsCall() != nullptr || li->GetPhysUse()) { + if (li->GetIsCall() != nullptr || (li->GetPhysUse() > 0)) { continue; } if (li->GetLastUse() > li->GetFirstDef()) { @@ -1064,6 +1024,7 @@ void LSRALinearScanRegAllocator::ComputeLiveInterval() /* Calculate the weight of a live interval for pre-spill and flexible spill */ void LSRALinearScanRegAllocator::LiveIntervalAnalysis() { + RA_TIMER_REGISTER(lsra, "LSRA BuildIntervalRanges"); for (uint32 bbIdx = 0; bbIdx < bfs->sortedBBs.size(); ++bbIdx) { BB *bb = bfs->sortedBBs[bbIdx]; @@ -1295,72 +1256,6 @@ uint32 LSRALinearScanRegAllocator::GetRegFromMask(uint32 mask, regno_t offset, c return bestReg; } -/* Handle adrp register assignment. Use the same register for the next instruction. */ -uint32 LSRALinearScanRegAllocator::GetSpecialPhysRegPattern(const LiveInterval &li) -{ - /* li's first def point */ - Insn *nInsn = nullptr; - if (nInsn == nullptr || !nInsn->IsMachineInstruction() || nInsn->IsDMBInsn() || li.GetLastUse() > nInsn->GetId()) { - return 0; - } - - const InsnDesc *md = nInsn->GetDesc(); - if (!md->GetOpndDes(0)->IsRegDef()) { - return 0; - } - Operand &opnd = nInsn->GetOperand(0); - if (!opnd.IsRegister()) { - return 0; - } - auto ®Opnd = static_cast(opnd); - if (!regOpnd.IsPhysicalRegister()) { - return 0; - } - uint32 regNO = regOpnd.GetRegisterNumber(); - if (!regInfo->IsPreAssignedReg(regNO)) { - return 0; - } - - /* next insn's dest is a physical param reg 'regNO'. return 'regNO' if dest of adrp is src of next insn */ - uint32 opndNum = nInsn->GetOperandSize(); - for (uint32 i = 1; i < opndNum; ++i) { - Operand &src = nInsn->GetOperand(i); - if (src.IsMemoryAccessOperand()) { - auto &memOpnd = static_cast(src); - Operand *base = memOpnd.GetBaseRegister(); - if (base != nullptr) { - auto *regSrc = static_cast(base); - uint32 srcRegNO = regSrc->GetRegisterNumber(); - if (li.GetRegNO() == srcRegNO) { - return regNO; - } - } - Operand *offset = memOpnd.GetIndexRegister(); - if (offset != nullptr) { - auto *regSrc = static_cast(offset); - uint32 srcRegNO = regSrc->GetRegisterNumber(); - if (li.GetRegNO() == srcRegNO) { - return regNO; - } - } - } else if (src.IsRegister()) { - auto ®Src = static_cast(src); - uint32 srcRegNO = regSrc.GetRegisterNumber(); - if (li.GetRegNO() == srcRegNO) { - const OpndDesc *regProp = md->GetOpndDes(i); - DEBUG_ASSERT(regProp != nullptr, - "pointer is null in LSRALinearScanRegAllocator::GetSpecialPhysRegPattern"); - bool srcIsDef = regProp->IsRegDef(); - if (srcIsDef) { - break; - } - return regNO; - } - } - } - return 0; -} - uint32 LSRALinearScanRegAllocator::FindAvailablePhyRegByFastAlloc(LiveInterval &li) { uint32 regNO = 0; @@ -1447,7 +1342,6 @@ void LSRALinearScanRegAllocator::InsertCallerSave(Insn &insn, Operand &opnd, boo LiveInterval *rli = liveIntervalsArray[vRegNO]; auto regType = rli->GetRegType(); - isSpillZero = false; if (!isDef && rli->IsNoNeedReloadPosition(insn.GetId())) { if (needDump) { LogInfo::MapleLogger() << "InsertCallerSave R" << rli->GetRegNO() << " assigned " @@ -1526,24 +1420,6 @@ MemOperand *LSRALinearScanRegAllocator::GetSpillMem(uint32 vRegNO, bool isDest, return regInfo->AdjustMemOperandIfOffsetOutOfRange(memOpnd, vRegNO, isDest, insn, regNO, isOutOfRange); } -/* Set a vreg in live interval as being marked for spill. */ -void LSRALinearScanRegAllocator::SetOperandSpill(Operand &opnd) -{ - auto ®Opnd = static_cast(opnd); - uint32 regNO = regOpnd.GetRegisterNumber(); - if (needDump) { - LogInfo::MapleLogger() << "SetOperandSpill " << regNO; - LogInfo::MapleLogger() << "(" << liveIntervalsArray[regNO]->GetFirstAcrossedCall(); - LogInfo::MapleLogger() << ", refCount " << liveIntervalsArray[regNO]->GetRefCount() << ")\n"; - } - - DEBUG_ASSERT(regNO < liveIntervalsArray.size(), - "index out of vector size in LSRALinearScanRegAllocator::SetOperandSpill"); - LiveInterval *li = liveIntervalsArray[regNO]; - li->SetStackSlot(kSpilled); - li->SetShouldSave(false); -} - /* * Generate spill/reload for an operand. * spill_idx : one of 3 phys regs set aside for the purpose of spills. @@ -1616,12 +1492,7 @@ void LSRALinearScanRegAllocator::SpillOperand(Insn &insn, Operand &opnd, bool is } bool isOutOfRange = false; - RegOperand *phyOpnd = nullptr; - if (isSpillZero) { - phyOpnd = &cgFunc->GetZeroOpnd(regSize); - } else { - phyOpnd = regInfo->GetOrCreatePhyRegOperand(static_cast(spReg), regSize, regType); - } + auto *phyOpnd = regInfo->GetOrCreatePhyRegOperand(static_cast(spReg), regSize, regType); li->SetAssignedReg(phyOpnd->GetRegisterNumber()); MemOperand *memOpnd = nullptr; @@ -1687,7 +1558,8 @@ void LSRALinearScanRegAllocator::FindLowestPrioInActive(LiveInterval *&targetLi, } } - float lowestPrio = (li0 != nullptr ? li0->GetPriority() : 1000.0); + constexpr float kBiggestFloat = 1000.0; + float lowestPrio = (li0 != nullptr ? li0->GetPriority() : kBiggestFloat); bool found = false; bool hintCalleeSavedReg = li0 && NeedSaveAcrossCall(*li0); MapleSet::iterator lowestIt; @@ -1699,7 +1571,7 @@ void LSRALinearScanRegAllocator::FindLowestPrioInActive(LiveInterval *&targetLi, continue; } /* 2. If li is pre-assigned to Physical register primitively, ignore it. */ - if (regInfo->IsPreAssignedReg(li->GetRegNO())) { + if (!regInfo->IsVirtualRegister(li->GetRegNO())) { continue; } /* 3. CalleeSavedReg is preferred here. If li is assigned to Non-CalleeSavedReg, ignore it. */ @@ -1781,49 +1653,50 @@ uint32 LSRALinearScanRegAllocator::HandleSpillForLi(LiveInterval &li) return newRegNO; } -uint32 LSRALinearScanRegAllocator::FindAvailablePhyReg(LiveInterval &li, bool isIntReg) +uint32 LSRALinearScanRegAllocator::FindAvailablePhyRegAcrossCall(LiveInterval &li, bool isIntReg) { - uint32 &callerRegMask = isIntReg ? intCallerMask : fpCallerMask; - uint32 &calleeRegMask = isIntReg ? intCalleeMask : fpCalleeMask; + uint32 callerRegMask = isIntReg ? intCallerMask : fpCallerMask; + uint32 calleeRegMask = isIntReg ? intCalleeMask : fpCalleeMask; regno_t reg0 = isIntReg ? firstIntReg : firstFpReg; - regno_t bestReg = 0; - regno_t secondReg = 0; - /* See if register is live accross a call */ - if (NeedSaveAcrossCall(li)) { - if (!li.IsAllInCatch() && !li.IsAllInCleanupOrFirstBB()) { - /* call in live interval, use callee if available */ - bestReg = GetRegFromMask(calleeRegMask, reg0, li); - if (bestReg != 0 && freeUntilPos[bestReg] >= li.GetLastUse()) { - li.SetShouldSave(false); - return bestReg; - } - } - /* can be optimize multi use between calls rather than in bb */ - if (bestReg == 0 || li.IsMultiUseInBB()) { - secondReg = GetRegFromMask(callerRegMask, reg0, li); - if (freeUntilPos[secondReg] >= li.GetLastUse()) { - li.SetShouldSave(true); - return secondReg; - } + /* call in live interval, use callee if available */ + auto bestReg = GetRegFromMask(calleeRegMask, reg0, li); + if (bestReg != 0 && freeUntilPos[bestReg] >= li.GetLastUse()) { + li.SetShouldSave(false); + return bestReg; + } + /* can be optimize multi use between calls rather than in bb */ + if (bestReg == 0 || li.IsMultiUseInBB()) { + auto secondReg = GetRegFromMask(callerRegMask, reg0, li); + if (freeUntilPos[secondReg] >= li.GetLastUse()) { + li.SetShouldSave(true); + return secondReg; } - } else { - /* Get forced register */ - uint32 forcedReg = GetSpecialPhysRegPattern(li); - if (forcedReg != 0) { - return forcedReg; - } - - bestReg = GetRegFromMask(intCallerMask, reg0, li); - if (bestReg == 0) { - bestReg = GetRegFromMask(intCalleeMask, reg0, li); - } else if (freeUntilPos[bestReg] < li.GetLastUse()) { - secondReg = GetRegFromMask(intCalleeMask, reg0, li); - if (secondReg != 0) { - bestReg = (freeUntilPos[bestReg] > freeUntilPos[secondReg]) ? bestReg : secondReg; - } + } + return 0; +} + +uint32 LSRALinearScanRegAllocator::FindAvailablePhyReg(LiveInterval &li, bool isIntReg) +{ + /* See if register is live accross a call */ + bool liAcrossCall = NeedSaveAcrossCall(li); + if (liAcrossCall && !regInfo->IsPrefCallerSaveRegs(li.GetRegType(), li.GetSpillSize())) { + return FindAvailablePhyRegAcrossCall(li, isIntReg); + } + + uint32 callerRegMask = isIntReg ? intCallerMask : fpCallerMask; + uint32 calleeRegMask = isIntReg ? intCalleeMask : fpCalleeMask; + regno_t reg0 = isIntReg ? firstIntReg : firstFpReg; + auto bestReg = GetRegFromMask(callerRegMask, reg0, li); + if (bestReg == 0) { + bestReg = GetRegFromMask(calleeRegMask, reg0, li); + } else if (freeUntilPos[bestReg] < li.GetLastUse()) { + auto secondReg = GetRegFromMask(calleeRegMask, reg0, li); + if (secondReg != 0) { + bestReg = (freeUntilPos[bestReg] > freeUntilPos[secondReg]) ? bestReg : secondReg; } } + if (bestReg != 0 && freeUntilPos[bestReg] < li.GetLastUse()) { DEBUG_ASSERT(freeUntilPos[bestReg] != 0, "impossible"); bestReg = 0; @@ -1889,10 +1762,7 @@ RegOperand *LSRALinearScanRegAllocator::GetReplaceUdOpnd(Insn &insn, Operand &op if (regType == kRegTyCc || regType == kRegTyVary) { return nullptr; } - if (regInfo->IsUntouchableReg(vRegNO)) { - return nullptr; - } - if (regOpnd->IsPhysicalRegister()) { + if (regInfo->IsUnconcernedReg(vRegNO) || !regInfo->IsVirtualRegister(vRegNO)) { return nullptr; } @@ -1935,10 +1805,7 @@ RegOperand *LSRALinearScanRegAllocator::GetReplaceOpnd(Insn &insn, Operand &opnd if (regType == kRegTyCc || regType == kRegTyVary) { return nullptr; } - if (regInfo->IsUntouchableReg(vRegNO)) { - return nullptr; - } - if (regOpnd->IsPhysicalRegister()) { + if (regInfo->IsUnconcernedReg(vRegNO) || !regInfo->IsVirtualRegister(vRegNO)) { return nullptr; } @@ -1974,7 +1841,7 @@ bool LSRALinearScanRegAllocator::CallerSaveOpt::UpdateLocalDefWithBBLiveIn(const for (uint32 i = 0; i < callerSaves.size(); ++i) { auto *li = callerSaves[i]; auto &defLiveIn = localDefLiveIn[i]; - auto &defLiveOut = localDefLiveOut[i]; + auto &defAfterInsn = localDefAfterInsn[i]; if (bb.GetLiveInRegNO().count(li->GetRegNO()) == 0) { continue; @@ -1984,14 +1851,14 @@ bool LSRALinearScanRegAllocator::CallerSaveOpt::UpdateLocalDefWithBBLiveIn(const } bool isLocalDef = true; for (auto *pred : bb.GetPreds()) { - if (defLiveOut.count(pred->GetId()) == 0) { + if (defAfterInsn.count(pred->GetId()) == 0) { isLocalDef = false; break; } } if (isLocalDef) { defLiveIn.insert(bb.GetId()); - defLiveOut.insert(bb.GetId()); + defAfterInsn.emplace(bb.GetId(), 0); changed = true; } } @@ -2003,19 +1870,24 @@ void LSRALinearScanRegAllocator::CallerSaveOpt::CollectCallerNoNeedReloadByInsn( auto curId = insn.GetId(); for (uint32 i = 0; i < callerSaves.size(); ++i) { auto *li = callerSaves[i]; - auto &defLiveOut = localDefLiveOut[i]; + auto &defLiveIn = localDefLiveIn[i]; + auto &defAfterInsn = localDefAfterInsn[i]; auto posRange = li->FindPosRange(curId); if (posRange == li->GetRanges().end() || posRange->GetStart() > curId) { continue; } if (insn.IsCall()) { - defLiveOut.erase(insn.GetBB()->GetId()); + defAfterInsn.erase(insn.GetBB()->GetId()); continue; } auto &usePositions = li->GetUsePositions(); if (std::binary_search(usePositions.begin(), usePositions.end(), curId)) { - if (defLiveOut.count(insn.GetBB()->GetId()) == 0) { - defLiveOut.insert(insn.GetBB()->GetId()); + auto iter = defAfterInsn.find(insn.GetBB()->GetId()); + if (iter == defAfterInsn.end() || iter->second > curId) { + defAfterInsn.insert_or_assign(insn.GetBB()->GetId(), curId); + continue; + } + if (iter->second == curId && defLiveIn.count(insn.GetBB()->GetId()) == 0) { continue; } li->AddNoNeedReloadPosition(curId); @@ -2050,6 +1922,7 @@ void LSRALinearScanRegAllocator::CallerSaveOpt::Run() /* Iterate through all instructions and change the vreg to preg. */ void LSRALinearScanRegAllocator::FinalizeRegisters() { + RA_TIMER_REGISTER(lsra, "LSRA FinalizeRegisters"); CallerSaveOpt opt(liveIntervalsArray, bfs); opt.Run(); for (BB *bb : bfs->sortedBBs) { @@ -2064,38 +1937,49 @@ void LSRALinearScanRegAllocator::FinalizeRegisters() /* Handle source(use) opernads first */ for (uint32 i = 0; i < opndNum; ++i) { - const OpndDesc *regProp = md->GetOpndDes(i); - DEBUG_ASSERT(regProp != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); - bool isDef = regProp->IsRegDef(); + const OpndDesc *opndDesc = md->GetOpndDes(i); + DEBUG_ASSERT(opndDesc != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); + Operand &opnd = insn->GetOperand(i); + bool isDef = (opndDesc->IsDef() && !opnd.IsMemoryAccessOperand()); if (isDef) { continue; } - Operand &opnd = insn->GetOperand(i); - RegOperand *phyOpnd = nullptr; if (opnd.IsList()) { - /* For arm32, not arm64 */ + auto &listOpnd = static_cast(opnd); + auto *newList = &cgFunc->GetOpndBuilder()->CreateList(cgFunc->GetFuncScopeAllocator()-> + GetMemPool()); + RegOperand *phyOpnd = nullptr; + for (auto *regOpnd : listOpnd.GetOperands()) { + if (regOpnd->IsPhysicalRegister()) { + phyOpnd = regOpnd; + } else { + phyOpnd = GetReplaceOpnd(*insn, *regOpnd, spillIdx, false); + } + newList->PushOpnd(*phyOpnd); + } + insn->SetOperand(i, *newList); } else if (opnd.IsMemoryAccessOperand()) { auto *memOpnd = - static_cast(static_cast(opnd).Clone(*cgFunc->GetMemoryPool())); + static_cast(static_cast(opnd).Clone(*cgFunc->GetMemoryPool())); DEBUG_ASSERT(memOpnd != nullptr, "memopnd is null in LSRALinearScanRegAllocator::FinalizeRegisters"); insn->SetOperand(i, *memOpnd); Operand *base = memOpnd->GetBaseRegister(); Operand *offset = memOpnd->GetIndexRegister(); if (base != nullptr) { - phyOpnd = GetReplaceOpnd(*insn, *base, spillIdx, false); + auto *phyOpnd = GetReplaceOpnd(*insn, *base, spillIdx, false); if (phyOpnd != nullptr) { memOpnd->SetBaseRegister(*phyOpnd); } } if (offset != nullptr) { - phyOpnd = GetReplaceOpnd(*insn, *offset, spillIdx, false); + auto *phyOpnd = GetReplaceOpnd(*insn, *offset, spillIdx, false); if (phyOpnd != nullptr) { memOpnd->SetIndexRegister(*phyOpnd); } } } else { - phyOpnd = GetReplaceOpnd(*insn, opnd, spillIdx, false); + auto *phyOpnd = GetReplaceOpnd(*insn, opnd, spillIdx, false); if (phyOpnd != nullptr) { insn->SetOperand(i, *phyOpnd); } @@ -2104,10 +1988,10 @@ void LSRALinearScanRegAllocator::FinalizeRegisters() /* Handle ud(use-def) opernads */ for (uint32 i = 0; i < opndNum; ++i) { - const OpndDesc *regProp = md->GetOpndDes(i); - DEBUG_ASSERT(regProp != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); + const OpndDesc *opndDesc = md->GetOpndDes(i); + DEBUG_ASSERT(opndDesc != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); Operand &opnd = insn->GetOperand(i); - bool isUseDef = regProp->IsRegDef() && regProp->IsRegUse(); + bool isUseDef = opndDesc->IsRegDef() && opndDesc->IsRegUse(); if (!isUseDef) { continue; } @@ -2119,20 +2003,32 @@ void LSRALinearScanRegAllocator::FinalizeRegisters() /* Handle dest(def) opernads last */ for (uint32 i = 0; i < opndNum; ++i) { - const OpndDesc *regProp = md->GetOpndDes(i); - DEBUG_ASSERT(regProp != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); + const OpndDesc *opndDesc = md->GetOpndDes(i); + DEBUG_ASSERT(opndDesc != nullptr, "pointer is null in LSRALinearScanRegAllocator::FinalizeRegisters"); Operand &opnd = insn->GetOperand(i); - bool isUse = (regProp->IsRegUse()) || (opnd.IsMemoryAccessOperand()); + bool isUse = (opndDesc->IsUse() || opnd.IsMemoryAccessOperand()); if (isUse) { continue; } - isSpillZero = false; - RegOperand *phyOpnd = GetReplaceOpnd(*insn, opnd, spillIdx, true); - if (phyOpnd != nullptr) { - insn->SetOperand(i, *phyOpnd); - if (isSpillZero) { - insn->GetBB()->RemoveInsn(*insn); + if (opnd.IsRegister()) { + RegOperand *phyOpnd = GetReplaceOpnd(*insn, opnd, spillIdx, true); + if (phyOpnd != nullptr) { + insn->SetOperand(i, *phyOpnd); } + } else if (opnd.IsList()) { + auto &listOpnd = static_cast(opnd); + auto *newList = &cgFunc->GetOpndBuilder()->CreateList(cgFunc-> + GetFuncScopeAllocator()->GetMemPool()); + RegOperand *phyOpnd = nullptr; + for (auto *regOpnd : listOpnd.GetOperands()) { + if (regOpnd->IsPhysicalRegister()) { + phyOpnd = regOpnd; + } else { + phyOpnd = GetReplaceOpnd(*insn, *regOpnd, spillIdx, true); + } + newList->PushOpnd(*phyOpnd); + } + insn->SetOperand(i, *newList); } } } @@ -2141,6 +2037,7 @@ void LSRALinearScanRegAllocator::FinalizeRegisters() void LSRALinearScanRegAllocator::CollectReferenceMap() { + RA_TIMER_REGISTER(lsra, "LSRA CollectReferenceMap"); const auto &referenceMapInsns = cgFunc->GetStackMapInsns(); if (needDump) { LogInfo::MapleLogger() << "===========reference map stack info================\n"; @@ -2205,7 +2102,7 @@ void LSRALinearScanRegAllocator::CollectReferenceMap() void LSRALinearScanRegAllocator::SolveRegOpndDeoptInfo(const RegOperand ®Opnd, DeoptInfo &deoptInfo, int32 deoptVregNO) const { - if (regOpnd.IsPhysicalRegister()) { + if (!regInfo->IsVirtualRegister(regOpnd)) { // Get Register No deoptInfo.RecordDeoptVreg2LocationInfo(deoptVregNO, LocationInfo({kInRegister, 0})); return; @@ -2231,6 +2128,7 @@ void LSRALinearScanRegAllocator::SolveMemOpndDeoptInfo(const MemOperand &memOpnd void LSRALinearScanRegAllocator::CollectDeoptInfo() { + RA_TIMER_REGISTER(lsra, "LSRA CollectReferenceMap"); const auto referenceMapInsns = cgFunc->GetStackMapInsns(); for (auto *insn : referenceMapInsns) { auto &deoptInfo = insn->GetStackMap()->GetDeoptInfo(); @@ -2292,6 +2190,7 @@ void LSRALinearScanRegAllocator::SetAllocMode() void LSRALinearScanRegAllocator::LinearScanRegAllocator() { + RA_TIMER_REGISTER(lsra, "LSRA LinearScanRegAllocator"); if (needDump) { PrintParamQueue("Initial param queue"); PrintCallQueue("Initial call queue"); @@ -2339,19 +2238,12 @@ bool LSRALinearScanRegAllocator::AllocateRegisters() liveIntervalsArray.resize(cgFunc->GetMaxVReg()); regInfo->Fini(); SetAllocMode(); -#ifdef RA_PERF_ANALYSIS - auto begin = std::chrono::system_clock::now(); -#endif if (needDump) { const MIRModule &mirModule = cgFunc->GetMirModule(); DotGenerator::GenerateDot("RA", *cgFunc, mirModule); DotGenerator::GenerateDot("RAe", *cgFunc, mirModule, true); LogInfo::MapleLogger() << "Entering LinearScanRegAllocator: " << cgFunc->GetName() << "\n"; } -/* ================= LiveInterval =============== */ -#ifdef RA_PERF_ANALYSIS - start = std::chrono::system_clock::now(); -#endif ComputeLiveInterval(); if (needDump) { @@ -2363,50 +2255,16 @@ bool LSRALinearScanRegAllocator::AllocateRegisters() LiveIntervalAnalysis(); } -#ifdef RA_PERF_ANALYSIS - end = std::chrono::system_clock::now(); - liveIntervalUS += std::chrono::duration_cast(end - start).count(); -#endif - -/* ================= LiveRange =============== */ -#ifdef RA_PERF_ANALYSIS - start = std::chrono::system_clock::now(); -#endif - SpillStackMapInfo(); - - if (needDump) { - PrintAllLiveRanges(); - } -#ifdef RA_PERF_ANALYSIS - end = std::chrono::system_clock::now(); - holesUS += std::chrono::duration_cast(end - start).count(); -#endif - /* ================= InitFreeRegPool =============== */ InitFreeRegPool(); -/* ================= LinearScanRegAllocator =============== */ -#ifdef RA_PERF_ANALYSIS - start = std::chrono::system_clock::now(); -#endif LinearScanRegAllocator(); -#ifdef RA_PERF_ANALYSIS - end = std::chrono::system_clock::now(); - lsraUS += std::chrono::duration_cast(end - start).count(); -#endif if (needDump) { PrintAllLiveRanges(); } -#ifdef RA_PERF_ANALYSIS - start = std::chrono::system_clock::now(); -#endif FinalizeRegisters(); -#ifdef RA_PERF_ANALYSIS - end = std::chrono::system_clock::now(); - finalizeUS += std::chrono::duration_cast(end - start).count(); -#endif CollectReferenceMap(); CollectDeoptInfo(); @@ -2428,11 +2286,6 @@ bool LSRALinearScanRegAllocator::AllocateRegisters() bfs = nullptr; /* bfs is not utilized outside the function. */ -#ifdef RA_PERF_ANALYSIS - end = std::chrono::system_clock::now(); - totalUS += std::chrono::duration_cast(end - begin).count(); -#endif - return true; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp index c04355fcee74a39b6dc3b7f152340448a813e499..92bebdbf1060e528138fdb57903cfc56ff594c65 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp @@ -470,9 +470,6 @@ void X64MPIsel::SelectLibCallNArg(const std::string &funcName, std::vectorGetOpndBuilder()->CreateList(); Insn &callInsn = AppendCall(x64::MOP_callq_l, targetOpnd, paramOpnds, retOpnds); - bool isFloat = IsPrimitiveFloat(retPrimType); - Insn::RetType insnRetType = isFloat ? Insn::kRegFloat : Insn::kRegInt; - callInsn.SetRetType(insnRetType); /* no ret function */ if (retOpnd == nullptr) { return; @@ -625,7 +622,6 @@ void X64MPIsel::SelectCall(CallNode &callNode) SelectCalleeReturn(retType, retOpnds); Insn &callInsn = AppendCall(x64::MOP_callq_l, targetOpnd, paramOpnds, retOpnds); - callInsn.SetRetType(Insn::kRegInt); if (retType != nullptr) { callInsn.SetRetSize(static_cast(retType->GetSize())); callInsn.SetIsCallReturnUnsigned(IsUnsignedInteger(retType->GetPrimType())); @@ -664,7 +660,6 @@ void X64MPIsel::SelectIcall(IcallNode &iCallNode, Operand &opnd0) SelectCalleeReturn(retType, retOpnds); Insn &callInsn = AppendCall(x64::MOP_callq_r, targetOpnd, paramOpnds, retOpnds); - callInsn.SetRetType(Insn::kRegInt); if (retType != nullptr) { callInsn.SetRetSize(static_cast(retType->GetSize())); callInsn.SetIsCallReturnUnsigned(IsUnsignedInteger(retType->GetPrimType())); @@ -981,7 +976,7 @@ Operand *X64MPIsel::SelectAddrofFunc(AddroffuncNode &expr, const BaseNode &paren cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType)); if (storageClass == maple::kScText && symbol->GetSKind() == maple::kStFunc) { ImmOperand &stOpnd = cgFunc->GetOpndBuilder()->CreateImm(*symbol, 0, 0); - X64MOP_t mOp = x64::MOP_movabs_s_r; + X64MOP_t mOp = x64::MOP_movabs_i_r; Insn &addrInsn = (cgFunc->GetInsnBuilder()->BuildInsn(mOp, X64CG::kMd[mOp])); addrInsn.AddOpndChain(stOpnd).AddOpndChain(resReg); cgFunc->GetCurBB()->AppendInsn(addrInsn); @@ -1125,7 +1120,7 @@ Operand *X64MPIsel::SelectStrLiteral(ConststrNode &constStr) if (c->GetPrimType() == PTY_ptr) { ImmOperand &stOpnd = cgFunc->GetOpndBuilder()->CreateImm(*labelSym, 0, 0); RegOperand &addrOpnd = cgFunc->GetOpndBuilder()->CreateVReg(k64BitSize, cgFunc->GetRegTyFromPrimTy(PTY_a64)); - Insn &addrOfInsn = (cgFunc->GetInsnBuilder()->BuildInsn(x64::MOP_movabs_s_r, X64CG::kMd[x64::MOP_movabs_s_r])); + Insn &addrOfInsn = (cgFunc->GetInsnBuilder()->BuildInsn(x64::MOP_movabs_i_r, X64CG::kMd[x64::MOP_movabs_i_r])); addrOfInsn.AddOpndChain(stOpnd).AddOpndChain(addrOpnd); cgFunc->GetCurBB()->AppendInsn(addrOfInsn); return &addrOpnd; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_abi.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_abi.cpp index 2e55d493aa8ff475ebf1273f48026118f25409f0..2df4d60db2f4c1b19e85b99eb63967ec82eac5ae 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_abi.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_abi.cpp @@ -66,29 +66,6 @@ bool IsCalleeSavedReg(X64reg reg) } } -bool IsParamReg(X64reg reg) -{ - switch (reg) { -/* integer registers */ -#define INT_REG(ID, PREF8, PREF8_16, PREF16, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, \ - isExtraSpill) \ - case R##ID: \ - return isParam; -#define INT_REG_ALIAS(ALIAS, ID) -#include "x64_int_regs.def" -#undef INT_REG -#undef INT_REG_ALIAS -/* fp-simd registers */ -#define FP_SIMD_REG(ID, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) \ - case V##ID: \ - return isParam; -#include "x64_fp_simd_regs.def" -#undef FP_SIMD_REG - default: - return false; - } -} - bool IsSpillReg(X64reg reg) { switch (reg) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp index 596a15914802ef693033b00218e080a080a1f2e5..e325100aea3c7ff2aa06a6236bdebfbecf139956 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp @@ -55,10 +55,6 @@ void X64CGFunc::MergeReturn() { CHECK_FATAL(false, "NIY"); } -void X64CGFunc::DetermineReturnTypeofCall() -{ - CHECK_FATAL(false, "NIY"); -} void X64CGFunc::HandleRCCall(bool begin, const MIRSymbol *retRef) { CHECK_FATAL(false, "NIY"); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_reg_info.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_reg_info.cpp index 927c3a62535c3fed3f5b80f88dd74743f28f0320..7906504f79c6de6cb348895361827b119bbcac5a 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_reg_info.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_reg_info.cpp @@ -48,20 +48,6 @@ void X64RegInfo::SaveCalleeSavedReg(MapleSet savedRegs) } } -bool X64RegInfo::IsSpecialReg(regno_t regno) const -{ - X64reg reg = static_cast(regno); - if ((reg == RBP) || (reg == RSP)) { - return true; - } - - /* when yieldpoint is enabled, the dedicated register(RYP) can not be allocated. */ - if (IsYieldPointReg(reg)) { - return true; - } - return false; -} - bool X64RegInfo::IsCalleeSavedReg(regno_t regno) const { return x64::IsCalleeSavedReg(static_cast(regno)); @@ -74,8 +60,13 @@ bool X64RegInfo::IsYieldPointReg(regno_t regno) const bool X64RegInfo::IsUnconcernedReg(regno_t regNO) const { + X64reg reg = static_cast(regNO); + if (reg == RBP || reg == RSP || reg == RIP) { + return true; + } + /* when yieldpoint is enabled, the RYP(R12) can not be used. */ - if (IsYieldPointReg(static_cast(regNO))) { + if (IsYieldPointReg(reg)) { return true; } return false; @@ -93,18 +84,6 @@ bool X64RegInfo::IsUnconcernedReg(const RegOperand ®Opnd) const void X64RegInfo::Fini() {} -ListOperand *X64RegInfo::CreateListOperand() -{ - CHECK_FATAL(false, "CreateListOperand, unsupported"); - return nullptr; -} - -Insn *X64RegInfo::BuildMovInstruction(Operand &opnd0, Operand &opnd1) -{ - CHECK_FATAL(false, "BuildMovInstruction, unsupported"); - return nullptr; -} - RegOperand *X64RegInfo::GetOrCreatePhyRegOperand(regno_t regNO, uint32 size, RegType kind, uint32 flag) { return &(GetCurrFunction()->GetOpndBuilder()->CreatePReg(regNO, size, kind)); @@ -162,13 +141,6 @@ Insn *X64RegInfo::BuildLdrInsn(uint32 regSize, PrimType stype, RegOperand &phyOp return &insn; } -Insn *X64RegInfo::BuildCommentInsn(const std::string &comment) -{ - CHECK_FATAL(false, "Comment Insn, unsupported"); - GetCurrFunction()->GetOpndBuilder()->CreateComment(comment); - return nullptr; -} - void X64RegInfo::FreeSpillRegMem(regno_t vrNum) { X64CGFunc *x64CGFunc = static_cast(GetCurrFunction()); diff --git a/ecmascript/compiler/codegen/maple/maple_util/include/mpl_timer.h b/ecmascript/compiler/codegen/maple/maple_util/include/mpl_timer.h index b33db3567b6a529d60c80d43e596abc2ebc1c1b1..6086f7b98fe998251adce65b49fdaf80f9694e4e 100644 --- a/ecmascript/compiler/codegen/maple/maple_util/include/mpl_timer.h +++ b/ecmascript/compiler/codegen/maple/maple_util/include/mpl_timer.h @@ -17,21 +17,118 @@ #define MAPLE_UTIL_INCLUDE_MPL_TIMER_H #include +#include +#include +#include +#include namespace maple { -class MPLTimer { + class MPLTimer { + public: + MPLTimer(); + ~MPLTimer(); + void Start(); + void Stop(); + long Elapsed() const; + long ElapsedMilliseconds() const; + long ElapsedMicroseconds() const; + + private: + std::chrono::system_clock::time_point startTime; + std::chrono::system_clock::time_point endTime; + }; + +class MPLTimerManager { public: - MPLTimer(); - ~MPLTimer(); - void Start(); - void Stop(); - long Elapsed(); - long ElapsedMilliseconds(); - long ElapsedMicroseconds(); + enum class Unit { + kMicroSeconds, // us + kMilliSeconds, // ms + kSeconds, // s + }; + + // time data + struct Timer { + void Start() noexcept + { + startTime = std::chrono::system_clock::now(); + ++count; + } + + void Stop() noexcept + { + useTime += (std::chrono::system_clock::now() - startTime); + } + + template + long Elapsed() const noexcept + { + return std::chrono::duration_cast(useTime).count(); + } + + std::chrono::system_clock::time_point startTime; + std::chrono::nanoseconds useTime; + uint32_t count = 0; // run count + }; + + MPLTimerManager() = default; + virtual ~MPLTimerManager() = default; + + void Clear() + { + allTimer.clear(); + } + + Timer &GetTimerFormKey(const std::string &key) + { + return allTimer[key]; + } + + template + std::string ConvertAllTimer2Str() const + { + std::ostringstream os; + for (auto &[key, timer] : allTimer) { + os << "\t" << key << ": "; + if constexpr (unit == Unit::kMicroSeconds) { + os << timer.Elapsed() << "us"; + } else if constexpr (unit == Unit::kMilliSeconds) { + os << timer.Elapsed() << "ms"; + } else { + static_assert(unit == Unit::kSeconds, "unknown units"); + os << timer.Elapsed() << "s"; + } + os << ", count: " << timer.count << std::endl; + } + return os.str(); + } + +private: + std::map allTimer; +}; + +class MPLTimerRegister { +public: + MPLTimerRegister(MPLTimerManager &timerM, const std::string &key) + { + timer = &timerM.GetTimerFormKey(key); + timer->Start(); + } + + ~MPLTimerRegister() + { + Stop(); + } + + void Stop() noexcept + { + if (timer != nullptr) { + timer->Stop(); + timer = nullptr; + } + } private: - std::chrono::system_clock::time_point startTime; - std::chrono::system_clock::time_point endTime; + MPLTimerManager::Timer *timer = nullptr; }; -} // namespace maple -#endif // MAPLE_UTIL_INCLUDE_MPL_TIMER_H +} // namespace maple +#endif // MAPLE_UTIL_INCLUDE_MPL_TIMER_H diff --git a/ecmascript/compiler/codegen/maple/maple_util/src/mpl_timer.cpp b/ecmascript/compiler/codegen/maple/maple_util/src/mpl_timer.cpp index 2f4e00bb6b2283f5dd54c828916f78a40a9af18a..b74e00861d8dc5e89749f68a62d4d338bb098474 100644 --- a/ecmascript/compiler/codegen/maple/maple_util/src/mpl_timer.cpp +++ b/ecmascript/compiler/codegen/maple/maple_util/src/mpl_timer.cpp @@ -31,17 +31,17 @@ void MPLTimer::Stop() endTime = std::chrono::system_clock::now(); } -long MPLTimer::Elapsed() +long MPLTimer::Elapsed() const { return std::chrono::duration_cast(endTime - startTime).count(); } -long MPLTimer::ElapsedMilliseconds() +long MPLTimer::ElapsedMilliseconds() const { return std::chrono::duration_cast(endTime - startTime).count(); } -long MPLTimer::ElapsedMicroseconds() +long MPLTimer::ElapsedMicroseconds() const { return std::chrono::duration_cast(endTime - startTime).count(); }