summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asmjit/src/asmjit/core/ralocal_p.h
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asmjit/src/asmjit/core/ralocal_p.h')
-rw-r--r--3rdparty/asmjit/src/asmjit/core/ralocal_p.h167
1 files changed, 66 insertions, 101 deletions
diff --git a/3rdparty/asmjit/src/asmjit/core/ralocal_p.h b/3rdparty/asmjit/src/asmjit/core/ralocal_p.h
index c944aad2bb4..63fd1b78aba 100644
--- a/3rdparty/asmjit/src/asmjit/core/ralocal_p.h
+++ b/3rdparty/asmjit/src/asmjit/core/ralocal_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_RALOCAL_P_H_INCLUDED
#define ASMJIT_CORE_RALOCAL_P_H_INCLUDED
@@ -38,10 +20,6 @@ ASMJIT_BEGIN_NAMESPACE
//! \addtogroup asmjit_ra
//! \{
-// ============================================================================
-// [asmjit::RALocalAllocator]
-// ============================================================================
-
//! Local register allocator.
class RALocalAllocator {
public:
@@ -50,50 +28,46 @@ public:
typedef RAAssignment::PhysToWorkMap PhysToWorkMap;
typedef RAAssignment::WorkToPhysMap WorkToPhysMap;
- //! Link to `RAPass`.
- RAPass* _pass;
+ //! Link to `BaseRAPass`.
+ BaseRAPass* _pass {};
//! Link to `BaseCompiler`.
- BaseCompiler* _cc;
+ BaseCompiler* _cc {};
//! Architecture traits.
- RAArchTraits _archTraits;
+ const ArchTraits* _archTraits {};
//! Registers available to the allocator.
- RARegMask _availableRegs;
+ RARegMask _availableRegs {};
//! Registers clobbered by the allocator.
- RARegMask _clobberedRegs;
+ RARegMask _clobberedRegs {};
//! Register assignment (current).
- RAAssignment _curAssignment;
+ RAAssignment _curAssignment {};
//! Register assignment used temporarily during assignment switches.
- RAAssignment _tmpAssignment;
+ RAAssignment _tmpAssignment {};
//! Link to the current `RABlock`.
- RABlock* _block;
+ RABlock* _block {};
//! InstNode.
- InstNode* _node;
+ InstNode* _node {};
//! RA instruction.
- RAInst* _raInst;
+ RAInst* _raInst {};
//! Count of all TiedReg's.
- uint32_t _tiedTotal;
+ uint32_t _tiedTotal {};
//! TiedReg's total counter.
- RARegCount _tiedCount;
+ RARegCount _tiedCount {};
+
+ //! Temporary workToPhysMap that can be used freely by the allocator.
+ WorkToPhysMap* _tmpWorkToPhysMap {};
//! \name Construction & Destruction
//! \{
- inline RALocalAllocator(RAPass* pass) noexcept
+ inline explicit RALocalAllocator(BaseRAPass* pass) noexcept
: _pass(pass),
_cc(pass->cc()),
_archTraits(pass->_archTraits),
- _availableRegs(pass->_availableRegs),
- _clobberedRegs(),
- _curAssignment(),
- _block(nullptr),
- _node(nullptr),
- _raInst(nullptr),
- _tiedTotal(),
- _tiedCount() {}
+ _availableRegs(pass->_availableRegs) {}
Error init() noexcept;
@@ -102,31 +76,31 @@ public:
//! \name Accessors
//! \{
- inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); }
- inline PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); }
- inline WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); }
+ ASMJIT_INLINE_NODEBUG RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); }
+ ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); }
+ ASMJIT_INLINE_NODEBUG WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); }
//! Returns the currently processed block.
- inline RABlock* block() const noexcept { return _block; }
+ ASMJIT_INLINE_NODEBUG RABlock* block() const noexcept { return _block; }
//! Sets the currently processed block.
- inline void setBlock(RABlock* block) noexcept { _block = block; }
+ ASMJIT_INLINE_NODEBUG void setBlock(RABlock* block) noexcept { _block = block; }
//! Returns the currently processed `InstNode`.
- inline InstNode* node() const noexcept { return _node; }
+ ASMJIT_INLINE_NODEBUG InstNode* node() const noexcept { return _node; }
//! Returns the currently processed `RAInst`.
- inline RAInst* raInst() const noexcept { return _raInst; }
+ ASMJIT_INLINE_NODEBUG RAInst* raInst() const noexcept { return _raInst; }
//! Returns all tied regs as `RATiedReg` array.
- inline RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); }
+ ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); }
//! Returns tied registers grouped by the given `group`.
- inline RATiedReg* tiedRegs(uint32_t group) const noexcept { return _raInst->tiedRegs(group); }
+ ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); }
//! Returns count of all TiedRegs used by the instruction.
- inline uint32_t tiedCount() const noexcept { return _tiedTotal; }
+ ASMJIT_INLINE_NODEBUG uint32_t tiedCount() const noexcept { return _tiedTotal; }
//! Returns count of TiedRegs used by the given register `group`.
- inline uint32_t tiedCount(uint32_t group) const noexcept { return _tiedCount.get(group); }
+ ASMJIT_INLINE_NODEBUG uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); }
- inline bool isGroupUsed(uint32_t group) const noexcept { return _tiedCount[group] != 0; }
+ ASMJIT_INLINE_NODEBUG bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; }
//! \}
@@ -135,30 +109,21 @@ public:
Error makeInitialAssignment() noexcept;
- Error replaceAssignment(
- const PhysToWorkMap* physToWorkMap,
- const WorkToPhysMap* workToPhysMap) noexcept;
+ Error replaceAssignment(const PhysToWorkMap* physToWorkMap) noexcept;
- //! Switch to the given assignment by reassigning all register and emitting
- //! code that reassigns them. This is always used to switch to a previously
- //! stored assignment.
+ //! Switch to the given assignment by reassigning all register and emitting code that reassigns them.
+ //! This is always used to switch to a previously stored assignment.
//!
- //! If `tryMode` is true then the final assignment doesn't have to be exactly
- //! same as specified by `dstPhysToWorkMap` and `dstWorkToPhysMap`. This mode
- //! is only used before conditional jumps that already have assignment to
- //! generate a code sequence that is always executed regardless of the flow.
- Error switchToAssignment(
- PhysToWorkMap* dstPhysToWorkMap,
- WorkToPhysMap* dstWorkToPhysMap,
- const ZoneBitVector& liveIn,
- bool dstReadOnly,
- bool tryMode) noexcept;
-
- inline Error spillRegsBeforeEntry(RABlock* block) noexcept {
- return spillGpScratchRegsBeforeEntry(block->entryScratchGpRegs());
+ //! If `tryMode` is true then the final assignment doesn't have to be exactly same as specified by `dstPhysToWorkMap`
+ //! and `dstWorkToPhysMap`. This mode is only used before conditional jumps that already have assignment to generate
+ //! a code sequence that is always executed regardless of the flow.
+ Error switchToAssignment(PhysToWorkMap* dstPhysToWorkMap, const ZoneBitVector& liveIn, bool dstReadOnly, bool tryMode) noexcept;
+
+ ASMJIT_INLINE_NODEBUG Error spillRegsBeforeEntry(RABlock* block) noexcept {
+ return spillScratchGpRegsBeforeEntry(block->entryScratchGpRegs());
}
- Error spillGpScratchRegsBeforeEntry(uint32_t scratchRegs) noexcept;
+ Error spillScratchGpRegsBeforeEntry(uint32_t scratchRegs) noexcept;
//! \}
@@ -181,11 +146,11 @@ public:
kCostOfDirtyFlag = kCostOfFrequency / 4
};
- inline uint32_t costByFrequency(float freq) const noexcept {
+ ASMJIT_INLINE_NODEBUG uint32_t costByFrequency(float freq) const noexcept {
return uint32_t(int32_t(freq * float(kCostOfFrequency)));
}
- inline uint32_t calculateSpillCost(uint32_t group, uint32_t workId, uint32_t assignedId) const noexcept {
+ inline uint32_t calculateSpillCost(RegGroup group, uint32_t workId, uint32_t assignedId) const noexcept {
RAWorkReg* workReg = workRegById(workId);
uint32_t cost = costByFrequency(workReg->liveStats().freq());
@@ -196,18 +161,18 @@ public:
}
//! Decides on register assignment.
- uint32_t decideOnAssignment(uint32_t group, uint32_t workId, uint32_t assignedId, uint32_t allocableRegs) const noexcept;
+ uint32_t decideOnAssignment(RegGroup group, uint32_t workId, uint32_t assignedId, RegMask allocableRegs) const noexcept;
- //! Decides on whether to MOVE or SPILL the given WorkReg, because it's allocated
- //! in a physical register that have to be used by another WorkReg.
+ //! Decides on whether to MOVE or SPILL the given WorkReg, because it's allocated in a physical register that have
+ //! to be used by another WorkReg.
//!
- //! The function must return either `RAAssignment::kPhysNone`, which means that
- //! the WorkReg of `workId` should be spilled, or a valid physical register ID,
- //! which means that the register should be moved to that physical register instead.
- uint32_t decideOnReassignment(uint32_t group, uint32_t workId, uint32_t assignedId, uint32_t allocableRegs) const noexcept;
+ //! The function must return either `RAAssignment::kPhysNone`, which means that the WorkReg of `workId` should be
+ //! spilled, or a valid physical register ID, which means that the register should be moved to that physical register
+ //! instead.
+ uint32_t decideOnReassignment(RegGroup group, uint32_t workId, uint32_t assignedId, RegMask allocableRegs) const noexcept;
//! Decides on best spill given a register mask `spillableRegs`
- uint32_t decideOnSpillFor(uint32_t group, uint32_t workId, uint32_t spillableRegs, uint32_t* spillWorkId) const noexcept;
+ uint32_t decideOnSpillFor(RegGroup group, uint32_t workId, RegMask spillableRegs, uint32_t* spillWorkId) const noexcept;
//! \}
@@ -216,56 +181,56 @@ public:
//! Emits a move between a destination and source register, and fixes the
//! register assignment.
- inline Error onMoveReg(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept {
+ inline Error onMoveReg(RegGroup group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept {
if (dstPhysId == srcPhysId) return kErrorOk;
_curAssignment.reassign(group, workId, dstPhysId, srcPhysId);
- return _pass->onEmitMove(workId, dstPhysId, srcPhysId);
+ return _pass->emitMove(workId, dstPhysId, srcPhysId);
}
//! Emits a swap between two physical registers and fixes their assignment.
//!
//! \note Target must support this operation otherwise this would ASSERT.
- inline Error onSwapReg(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept {
+ inline Error onSwapReg(RegGroup group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept {
_curAssignment.swap(group, aWorkId, aPhysId, bWorkId, bPhysId);
- return _pass->onEmitSwap(aWorkId, aPhysId, bWorkId, bPhysId);
+ return _pass->emitSwap(aWorkId, aPhysId, bWorkId, bPhysId);
}
//! Emits a load from [VirtReg/WorkReg]'s spill slot to a physical register
//! and makes it assigned and clean.
- inline Error onLoadReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept {
+ inline Error onLoadReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept {
_curAssignment.assign(group, workId, physId, RAAssignment::kClean);
- return _pass->onEmitLoad(workId, physId);
+ return _pass->emitLoad(workId, physId);
}
//! Emits a save a physical register to a [VirtReg/WorkReg]'s spill slot,
//! keeps it assigned, and makes it clean.
- inline Error onSaveReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept {
+ inline Error onSaveReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept {
ASMJIT_ASSERT(_curAssignment.workToPhysId(group, workId) == physId);
ASMJIT_ASSERT(_curAssignment.physToWorkId(group, physId) == workId);
_curAssignment.makeClean(group, workId, physId);
- return _pass->onEmitSave(workId, physId);
+ return _pass->emitSave(workId, physId);
}
//! Assigns a register, the content of it is undefined at this point.
- inline Error onAssignReg(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept {
+ inline Error onAssignReg(RegGroup group, uint32_t workId, uint32_t physId, bool dirty) noexcept {
_curAssignment.assign(group, workId, physId, dirty);
return kErrorOk;
}
//! Spills a variable/register, saves the content to the memory-home if modified.
- inline Error onSpillReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept {
+ inline Error onSpillReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept {
if (_curAssignment.isPhysDirty(group, physId))
ASMJIT_PROPAGATE(onSaveReg(group, workId, physId));
return onKillReg(group, workId, physId);
}
- inline Error onDirtyReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept {
+ inline Error onDirtyReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept {
_curAssignment.makeDirty(group, workId, physId);
return kErrorOk;
}
- inline Error onKillReg(uint32_t group, uint32_t workId, uint32_t physId) noexcept {
+ inline Error onKillReg(RegGroup group, uint32_t workId, uint32_t physId) noexcept {
_curAssignment.unassign(group, workId, physId);
return kErrorOk;
}