diff options
Diffstat (limited to 'src/asmjit/core/raassignment_p.h')
-rw-r--r-- | src/asmjit/core/raassignment_p.h | 132 |
1 files changed, 57 insertions, 75 deletions
diff --git a/src/asmjit/core/raassignment_p.h b/src/asmjit/core/raassignment_p.h index 6b5df54..22a97e2 100644 --- a/src/asmjit/core/raassignment_p.h +++ b/src/asmjit/core/raassignment_p.h @@ -1,25 +1,7 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED #define ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED @@ -35,10 +17,12 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_ra //! \{ -// ============================================================================ -// [asmjit::RAAssignment] -// ============================================================================ - +//! Holds the current register assignment. +//! +//! Has two purposes: +//! +//! 1. Holds register assignment of a local register allocator (see \ref RALocalAllocator). +//! 2. Holds register assignment of the entry of basic blocks (see \ref RABlock). class RAAssignment { public: ASMJIT_NONCOPYABLE(RAAssignment) @@ -120,6 +104,9 @@ public: } }; + //! \name Members + //! \{ + //! Physical registers layout. Layout _layout; //! WorkReg to PhysReg mapping. @@ -127,7 +114,9 @@ public: //! PhysReg to WorkReg mapping and assigned/dirty bits. PhysToWorkMap* _physToWorkMap; //! Optimization to translate PhysRegs to WorkRegs faster. - uint32_t* _physToWorkIds[BaseReg::kGroupVirt]; + Support::Array<uint32_t*, Globals::kNumVirtGroups> _physToWorkIds; + + //! \} //! \name Construction & Destruction //! \{ @@ -137,31 +126,30 @@ public: resetMaps(); } - inline void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { + ASMJIT_FORCE_INLINE void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { // Layout must be initialized before data. ASMJIT_ASSERT(_physToWorkMap == nullptr); ASMJIT_ASSERT(_workToPhysMap == nullptr); _layout.physIndex.buildIndexes(physCount); _layout.physCount = physCount; - _layout.physTotal = uint32_t(_layout.physIndex[BaseReg::kGroupVirt - 1]) + - uint32_t(_layout.physCount[BaseReg::kGroupVirt - 1]) ; + _layout.physTotal = uint32_t(_layout.physIndex[RegGroup::kMaxVirt]) + + uint32_t(_layout.physCount[RegGroup::kMaxVirt]) ; _layout.workCount = workRegs.size(); _layout.workRegs = &workRegs; } - inline void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { + ASMJIT_FORCE_INLINE void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { _physToWorkMap = physToWorkMap; _workToPhysMap = workToPhysMap; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) + for (RegGroup group : RegGroupVirtValues{}) _physToWorkIds[group] = physToWorkMap->workIds + _layout.physIndex.get(group); } - inline void resetMaps() noexcept { + ASMJIT_FORCE_INLINE void resetMaps() noexcept { _physToWorkMap = nullptr; _workToPhysMap = nullptr; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = nullptr; + _physToWorkIds.fill(nullptr); } //! \} @@ -174,30 +162,30 @@ public: inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } - inline uint32_t assigned(uint32_t group) const noexcept { return _physToWorkMap->assigned[group]; } + inline uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; } inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } - inline uint32_t dirty(uint32_t group) const noexcept { return _physToWorkMap->dirty[group]; } + inline RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; } - inline uint32_t workToPhysId(uint32_t group, uint32_t workId) const noexcept { + inline uint32_t workToPhysId(RegGroup group, uint32_t workId) const noexcept { DebugUtils::unused(group); ASMJIT_ASSERT(workId != kWorkNone); ASMJIT_ASSERT(workId < _layout.workCount); return _workToPhysMap->physIds[workId]; } - inline uint32_t physToWorkId(uint32_t group, uint32_t physId) const noexcept { + inline uint32_t physToWorkId(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return _physToWorkIds[group][physId]; } - inline bool isPhysAssigned(uint32_t group, uint32_t physId) const noexcept { + inline bool isPhysAssigned(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return Support::bitTest(_physToWorkMap->assigned[group], physId); } - inline bool isPhysDirty(uint32_t group, uint32_t physId) const noexcept { + inline bool isPhysDirty(RegGroup group, uint32_t physId) const noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); return Support::bitTest(_physToWorkMap->dirty[group], physId); } @@ -205,15 +193,15 @@ public: //! \} //! \name Assignment + //! + //! These are low-level allocation helpers that are used to update the current mappings between physical and + //! virt/work registers and also to update masks that represent allocated and dirty registers. These functions + //! don't emit any code; they are only used to update and keep all mappings in sync. + //! //! \{ - // These are low-level allocation helpers that are used to update the current - // mappings between physical and virt/work registers and also to update masks - // that represent allocated and dirty registers. These functions don't emit - // any code; they are only used to update and keep all mappings in sync. - //! Assign [VirtReg/WorkReg] to a physical register. - ASMJIT_INLINE void assign(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept { + inline void assign(RegGroup group, uint32_t workId, uint32_t physId, bool dirty) noexcept { ASMJIT_ASSERT(workToPhysId(group, workId) == kPhysNone); ASMJIT_ASSERT(physToWorkId(group, physId) == kWorkNone); ASMJIT_ASSERT(!isPhysAssigned(group, physId)); @@ -222,15 +210,15 @@ public: _workToPhysMap->physIds[workId] = uint8_t(physId); _physToWorkIds[group][physId] = workId; - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->assigned[group] |= regMask; - _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool<uint32_t>(dirty); + _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool<RegMask>(dirty); verify(); } //! Reassign [VirtReg/WorkReg] to `dstPhysId` from `srcPhysId`. - ASMJIT_INLINE void reassign(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { + inline void reassign(RegGroup group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { ASMJIT_ASSERT(dstPhysId != srcPhysId); ASMJIT_ASSERT(workToPhysId(group, workId) == srcPhysId); ASMJIT_ASSERT(physToWorkId(group, srcPhysId) == workId); @@ -241,19 +229,19 @@ public: _physToWorkIds[group][srcPhysId] = kWorkNone; _physToWorkIds[group][dstPhysId] = workId; - uint32_t srcMask = Support::bitMask(srcPhysId); - uint32_t dstMask = Support::bitMask(dstPhysId); + RegMask srcMask = Support::bitMask(srcPhysId); + RegMask dstMask = Support::bitMask(dstPhysId); - uint32_t dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; - uint32_t regMask = dstMask | srcMask; + bool dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; + RegMask regMask = dstMask | srcMask; _physToWorkMap->assigned[group] ^= regMask; - _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool<uint32_t>(dirty); + _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool<RegMask>(dirty); verify(); } - ASMJIT_INLINE void swap(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { + inline void swap(RegGroup group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { ASMJIT_ASSERT(aPhysId != bPhysId); ASMJIT_ASSERT(workToPhysId(group, aWorkId) == aPhysId); ASMJIT_ASSERT(workToPhysId(group, bWorkId) == bPhysId); @@ -267,21 +255,17 @@ public: _physToWorkIds[group][aPhysId] = bWorkId; _physToWorkIds[group][bPhysId] = aWorkId; - uint32_t aMask = Support::bitMask(aPhysId); - uint32_t bMask = Support::bitMask(bPhysId); - - uint32_t flipMask = Support::bitMaskFromBool<uint32_t>( - ((_physToWorkMap->dirty[group] & aMask) != 0) ^ - ((_physToWorkMap->dirty[group] & bMask) != 0)); - - uint32_t regMask = aMask | bMask; + RegMask aMask = Support::bitMask(aPhysId); + RegMask bMask = Support::bitMask(bPhysId); + RegMask flipMask = Support::bitMaskFromBool<RegMask>(((_physToWorkMap->dirty[group] & aMask) != 0) ^ ((_physToWorkMap->dirty[group] & bMask) != 0)); + RegMask regMask = aMask | bMask; _physToWorkMap->dirty[group] ^= regMask & flipMask; verify(); } //! Unassign [VirtReg/WorkReg] from a physical register. - ASMJIT_INLINE void unassign(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void unassign(RegGroup group, uint32_t workId, uint32_t physId) noexcept { ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); ASMJIT_ASSERT(workToPhysId(group, workId) == physId); ASMJIT_ASSERT(physToWorkId(group, physId) == workId); @@ -290,22 +274,22 @@ public: _workToPhysMap->physIds[workId] = kPhysNone; _physToWorkIds[group][physId] = kWorkNone; - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->assigned[group] &= ~regMask; _physToWorkMap->dirty[group] &= ~regMask; verify(); } - inline void makeClean(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void makeClean(RegGroup group, uint32_t workId, uint32_t physId) noexcept { DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->dirty[group] &= ~regMask; } - inline void makeDirty(uint32_t group, uint32_t workId, uint32_t physId) noexcept { + inline void makeDirty(RegGroup group, uint32_t workId, uint32_t physId) noexcept { DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); + RegMask regMask = Support::bitMask(physId); _physToWorkMap->dirty[group] |= regMask; } @@ -314,12 +298,10 @@ public: //! \name Utilities //! \{ - inline void swap(RAAssignment& other) noexcept { + ASMJIT_FORCE_INLINE void swap(RAAssignment& other) noexcept { std::swap(_workToPhysMap, other._workToPhysMap); std::swap(_physToWorkMap, other._physToWorkMap); - - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - std::swap(_physToWorkIds[group], other._physToWorkIds[group]); + _physToWorkIds.swap(other._physToWorkIds); } inline void copyFrom(const PhysToWorkMap* physToWorkMap, const WorkToPhysMap* workToPhysMap) noexcept { @@ -373,7 +355,7 @@ public: uint32_t physId = _workToPhysMap->physIds[workId]; if (physId != kPhysNone) { const RAWorkReg* workReg = _layout.workRegs->at(workId); - uint32_t group = workReg->group(); + RegGroup group = workReg->group(); ASMJIT_ASSERT(_physToWorkIds[group][physId] == workId); } } @@ -381,7 +363,7 @@ public: // Verify PhysToWorkMap. { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { + for (RegGroup group : RegGroupVirtValues{}) { uint32_t physCount = _layout.physCount[group]; for (uint32_t physId = 0; physId < physCount; physId++) { uint32_t workId = _physToWorkIds[group][physId]; |