LCOV - code coverage report
Current view: top level - asmjit - x86regalloc_p.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 34 49 69.4 %
Date: 2024-10-11 08:09:49 Functions: 0 0 -

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2008-2017, Petr Kobalicek
       3             : 
       4             : This software is provided 'as-is', without any express or implied
       5             : warranty. In no event will the authors be held liable for any damages
       6             : arising from the use of this software.
       7             : 
       8             : Permission is granted to anyone to use this software for any purpose,
       9             : including commercial applications, and to alter it and redistribute it
      10             : freely, subject to the following restrictions:
      11             : 
      12             : 1. The origin of this software must not be misrepresented; you must not
      13             :    claim that you wrote the original software. If you use this software
      14             :    in a product, an acknowledgment in the product documentation would be
      15             :    appreciated but is not required.
      16             : 2. Altered source versions must be plainly marked as such, and must not be
      17             :    misrepresented as being the original software.
      18             : 3. This notice may not be removed or altered from any source distribution.
      19             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      20             : #ifndef __PLUMED_asmjit_x86regalloc_p_h
      21             : #define __PLUMED_asmjit_x86regalloc_p_h
      22             : #ifdef __PLUMED_HAS_ASMJIT
      23             : #pragma GCC diagnostic push
      24             : #pragma GCC diagnostic ignored "-Wpedantic"
      25             : // [AsmJit]
      26             : // Complete x86/x64 JIT and Remote Assembler for C++.
      27             : //
      28             : // [License]
      29             : // Zlib - See LICENSE.md file in the package.
      30             : 
      31             : // [Guard]
      32             : #ifndef _ASMJIT_X86_X86REGALLOC_P_H
      33             : #define _ASMJIT_X86_X86REGALLOC_P_H
      34             : 
      35             : #include "./asmjit_build.h"
      36             : #if !defined(ASMJIT_DISABLE_COMPILER)
      37             : 
      38             : // [Dependencies]
      39             : #include "./codecompiler.h"
      40             : #include "./regalloc_p.h"
      41             : #include "./utils.h"
      42             : #include "./x86assembler.h"
      43             : #include "./x86compiler.h"
      44             : #include "./x86misc.h"
      45             : 
      46             : // [Api-Begin]
      47             : #include "./asmjit_apibegin.h"
      48             : 
      49             : namespace PLMD {
      50             : namespace asmjit {
      51             : 
      52             : //! \addtogroup asmjit_x86
      53             : //! \{
      54             : 
      55             : // ============================================================================
      56             : // [asmjit::X86RAData]
      57             : // ============================================================================
      58             : 
      59             : struct X86RAData : public RAData {
      60       81036 :   ASMJIT_INLINE X86RAData(uint32_t tiedTotal) noexcept : RAData(tiedTotal) {
      61             :     inRegs.reset();
      62             :     outRegs.reset();
      63             :     clobberedRegs.reset();
      64             :     tiedIndex.reset();
      65             :     tiedCount.reset();
      66             :   }
      67             : 
      68             :   // --------------------------------------------------------------------------
      69             :   // [Accessors]
      70             :   // --------------------------------------------------------------------------
      71             : 
      72             :   //! Get TiedReg array.
      73             :   ASMJIT_INLINE TiedReg* getTiedArray() const noexcept {
      74       36630 :     return const_cast<TiedReg*>(tiedArray);
      75             :   }
      76             : 
      77             :   //! Get TiedReg array for a given register `kind`.
      78             :   ASMJIT_INLINE TiedReg* getTiedArrayByKind(uint32_t kind) const noexcept {
      79       99048 :     return const_cast<TiedReg*>(tiedArray) + tiedIndex.get(kind);
      80             :   }
      81             : 
      82             :   //! Get TiedReg index for a given register `kind`.
      83             :   ASMJIT_INLINE uint32_t getTiedStart(uint32_t kind) const noexcept {
      84             :     return tiedIndex.get(kind);
      85             :   }
      86             : 
      87             :   //! Get TiedReg count for a given register `kind`.
      88             :   ASMJIT_INLINE uint32_t getTiedCountByKind(uint32_t kind) const noexcept {
      89             :     return tiedCount.get(kind);
      90             :   }
      91             : 
      92             :   //! Get TiedReg at the specified `index`.
      93             :   ASMJIT_INLINE TiedReg* getTiedAt(uint32_t index) const noexcept {
      94             :     ASMJIT_ASSERT(index < tiedTotal);
      95             :     return getTiedArray() + index;
      96             :   }
      97             : 
      98             :   //! Get TiedReg at the specified index for a given register `kind`.
      99             :   ASMJIT_INLINE TiedReg* getTiedAtByKind(uint32_t kind, uint32_t index) const noexcept {
     100             :     ASMJIT_ASSERT(index < tiedCount._regs[kind]);
     101             :     return getTiedArrayByKind(kind) + index;
     102             :   }
     103             : 
     104             :   ASMJIT_INLINE void setTiedAt(uint32_t index, TiedReg& tied) noexcept {
     105             :     ASMJIT_ASSERT(index < tiedTotal);
     106       61374 :     tiedArray[index] = tied;
     107             :   }
     108             : 
     109             :   // --------------------------------------------------------------------------
     110             :   // [Utils]
     111             :   // --------------------------------------------------------------------------
     112             : 
     113             :   //! Find TiedReg.
     114             :   ASMJIT_INLINE TiedReg* findTied(VirtReg* vreg) const noexcept {
     115             :     TiedReg* tiedArray = getTiedArray();
     116             :     uint32_t tiedCount = tiedTotal;
     117             : 
     118             :     for (uint32_t i = 0; i < tiedCount; i++)
     119             :       if (tiedArray[i].vreg == vreg)
     120             :         return &tiedArray[i];
     121             : 
     122             :     return nullptr;
     123             :   }
     124             : 
     125             :   //! Find TiedReg (by class).
     126             :   ASMJIT_INLINE TiedReg* findTiedByKind(uint32_t kind, VirtReg* vreg) const noexcept {
     127             :     TiedReg* tiedArray = getTiedArrayByKind(kind);
     128             :     uint32_t tiedCount = getTiedCountByKind(kind);
     129             : 
     130      209446 :     for (uint32_t i = 0; i < tiedCount; i++)
     131      140266 :       if (tiedArray[i].vreg == vreg)
     132             :         return &tiedArray[i];
     133             : 
     134             :     return nullptr;
     135             :   }
     136             : 
     137             :   // --------------------------------------------------------------------------
     138             :   // [Members]
     139             :   // --------------------------------------------------------------------------
     140             : 
     141             :   //! Special registers on input.
     142             :   //!
     143             :   //! Special register(s) restricted to one or more physical register. If there
     144             :   //! is more than one special register it means that we have to duplicate the
     145             :   //! variable content to all of them (it means that the same variable was used
     146             :   //! by two or more operands). We forget about duplicates after the register
     147             :   //! allocation finishes and marks all duplicates as non-assigned.
     148             :   X86RegMask inRegs;
     149             : 
     150             :   //! Special registers on output.
     151             :   //!
     152             :   //! Special register(s) used on output. Each variable can have only one
     153             :   //! special register on the output, 'X86RAData' contains all registers from
     154             :   //! all 'TiedReg's.
     155             :   X86RegMask outRegs;
     156             : 
     157             :   //! Clobbered registers (by a function call).
     158             :   X86RegMask clobberedRegs;
     159             : 
     160             :   //! Start indexes of `TiedReg`s per register kind.
     161             :   X86RegCount tiedIndex;
     162             :   //! Count of variables per register kind.
     163             :   X86RegCount tiedCount;
     164             : 
     165             :   //! Linked registers.
     166             :   TiedReg tiedArray[1];
     167             : };
     168             : 
     169             : // ============================================================================
     170             : // [asmjit::X86StateCell]
     171             : // ============================================================================
     172             : 
     173             : //! X86/X64 state-cell.
     174             : union X86StateCell {
     175             :   // --------------------------------------------------------------------------
     176             :   // [Accessors]
     177             :   // --------------------------------------------------------------------------
     178             : 
     179           0 :   ASMJIT_INLINE uint32_t getState() const noexcept { return _state; }
     180           0 :   ASMJIT_INLINE void setState(uint32_t state) noexcept { _state = static_cast<uint8_t>(state); }
     181             : 
     182             :   // --------------------------------------------------------------------------
     183             :   // [Reset]
     184             :   // --------------------------------------------------------------------------
     185             : 
     186           0 :   ASMJIT_INLINE void reset() noexcept { _packed = 0; }
     187             : 
     188             :   // --------------------------------------------------------------------------
     189             :   // [Members]
     190             :   // --------------------------------------------------------------------------
     191             : 
     192             :   uint8_t _packed;
     193             : 
     194             :   struct {
     195             :     uint8_t _state : 2;
     196             :     uint8_t _unused : 6;
     197             :   };
     198             : };
     199             : 
     200             : // ============================================================================
     201             : // [asmjit::X86RAState]
     202             : // ============================================================================
     203             : 
     204             : //! X86/X64 state.
     205             : struct X86RAState : RAState {
     206             :   enum {
     207             :     //! Base index of GP registers.
     208             :     kGpIndex = 0,
     209             :     //! Count of GP registers.
     210             :     kGpCount = 16,
     211             : 
     212             :     //! Base index of MMX registers.
     213             :     kMmIndex = kGpIndex + kGpCount,
     214             :     //! Count of Mm registers.
     215             :     kMmCount = 8,
     216             : 
     217             :     //! Base index of XMM registers.
     218             :     kXmmIndex = kMmIndex + kMmCount,
     219             :     //! Count of XMM registers.
     220             :     kXmmCount = 16,
     221             : 
     222             :     //! Count of all registers in `X86RAState`.
     223             :     kAllCount = kXmmIndex + kXmmCount
     224             :   };
     225             : 
     226             :   // --------------------------------------------------------------------------
     227             :   // [Accessors]
     228             :   // --------------------------------------------------------------------------
     229             : 
     230             :   ASMJIT_INLINE VirtReg** getList() {
     231             :     return _list;
     232             :   }
     233             : 
     234             :   ASMJIT_INLINE VirtReg** getListByKind(uint32_t kind) {
     235             :     switch (kind) {
     236        3272 :       case X86Reg::kKindGp : return _listGp;
     237        3272 :       case X86Reg::kKindMm : return _listMm;
     238        8896 :       case X86Reg::kKindVec: return _listXmm;
     239             : 
     240             :       default:
     241             :         return nullptr;
     242             :     }
     243             :   }
     244             : 
     245             :   // --------------------------------------------------------------------------
     246             :   // [Clear]
     247             :   // --------------------------------------------------------------------------
     248             : 
     249             :   ASMJIT_INLINE void reset(size_t numCells) {
     250             :     ::memset(this, 0, kAllCount * sizeof(VirtReg*) +
     251             :                       2         * sizeof(X86RegMask) +
     252             :                       numCells  * sizeof(X86StateCell));
     253             :   }
     254             : 
     255             :   // --------------------------------------------------------------------------
     256             :   // [Members]
     257             :   // --------------------------------------------------------------------------
     258             : 
     259             :   union {
     260             :     //! List of all allocated variables in one array.
     261             :     VirtReg* _list[kAllCount];
     262             : 
     263             :     struct {
     264             :       //! Allocated GP registers.
     265             :       VirtReg* _listGp[kGpCount];
     266             :       //! Allocated MMX registers.
     267             :       VirtReg* _listMm[kMmCount];
     268             :       //! Allocated XMM registers.
     269             :       VirtReg* _listXmm[kXmmCount];
     270             :     };
     271             :   };
     272             : 
     273             :   //! Occupied registers (mask).
     274             :   X86RegMask _occupied;
     275             :   //! Modified registers (mask).
     276             :   X86RegMask _modified;
     277             : 
     278             :   //! Variables data, the length is stored in `X86RAPass`.
     279             :   X86StateCell _cells[1];
     280             : };
     281             : 
     282             : // ============================================================================
     283             : // [asmjit::X86RAPass]
     284             : // ============================================================================
     285             : 
     286             : #if defined(ASMJIT_DEBUG)
     287             : # define ASMJIT_X86_CHECK_STATE _checkState();
     288             : #else
     289             : # define ASMJIT_X86_CHECK_STATE
     290             : #endif // ASMJIT_DEBUG
     291             : 
     292             : //! \internal
     293             : //!
     294             : //! X86 register allocator pipeline.
     295             : //!
     296             : //! Takes care of generating function prologs and epilogs, and also performs
     297             : //! register allocation.
     298             : class X86RAPass : public RAPass {
     299             : public:
     300             :   ASMJIT_NONCOPYABLE(X86RAPass)
     301             :   typedef RAPass Base;
     302             : 
     303             :   enum RegOp {
     304             :     kRegOpMove,
     305             :     kRegOpLoad,
     306             :     kRegOpSave
     307             :   };
     308             : 
     309             :   // --------------------------------------------------------------------------
     310             :   // [Construction / Destruction]
     311             :   // --------------------------------------------------------------------------
     312             : 
     313             :   X86RAPass() noexcept;
     314             :   virtual ~X86RAPass() noexcept;
     315             : 
     316             :   // --------------------------------------------------------------------------
     317             :   // [Interface]
     318             :   // --------------------------------------------------------------------------
     319             : 
     320             :   virtual Error process(Zone* zone) noexcept override;
     321             :   virtual Error prepare(CCFunc* func) noexcept override;
     322             : 
     323             :   // --------------------------------------------------------------------------
     324             :   // [ArchInfo]
     325             :   // --------------------------------------------------------------------------
     326             : 
     327             :   ASMJIT_INLINE uint32_t getGpSize() const noexcept { return _zsp.getSize(); }
     328             : 
     329             :   // --------------------------------------------------------------------------
     330             :   // [Accessors]
     331             :   // --------------------------------------------------------------------------
     332             : 
     333             :   //! Get compiler as `X86Compiler`.
     334      119408 :   ASMJIT_INLINE X86Compiler* cc() const noexcept { return static_cast<X86Compiler*>(_cb); }
     335             :   //! Get clobbered registers (global).
     336             :   ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t kind) noexcept { return _clobberedRegs.get(kind); }
     337             : 
     338             :   // --------------------------------------------------------------------------
     339             :   // [Helpers]
     340             :   // --------------------------------------------------------------------------
     341             : 
     342             :   ASMJIT_INLINE X86RAData* newRAData(uint32_t tiedTotal) noexcept {
     343       40518 :     return new(_zone->alloc(sizeof(X86RAData) + tiedTotal * sizeof(TiedReg))) X86RAData(tiedTotal);
     344             :   }
     345             : 
     346             :   // --------------------------------------------------------------------------
     347             :   // [Emit]
     348             :   // --------------------------------------------------------------------------
     349             : 
     350             :   // Tiny wrappers that call `X86Internal::emit...()`.
     351             :   Error emitMove(VirtReg* vreg, uint32_t dstId, uint32_t srcId, const char* reason);
     352             :   Error emitLoad(VirtReg* vreg, uint32_t id, const char* reason);
     353             :   Error emitSave(VirtReg* vreg, uint32_t id, const char* reason);
     354             :   Error emitSwapGp(VirtReg* aVReg, VirtReg* bVReg, uint32_t aId, uint32_t bId, const char* reason) noexcept;
     355             : 
     356             :   Error emitImmToReg(uint32_t dstTypeId, uint32_t dstPhysId, const Imm* src) noexcept;
     357             :   Error emitImmToStack(uint32_t dstTypeId, const X86Mem* dst, const Imm* src) noexcept;
     358             :   Error emitRegToStack(uint32_t dstTypeId, const X86Mem* dst, uint32_t srcTypeId, uint32_t srcPhysId) noexcept;
     359             : 
     360             :   // --------------------------------------------------------------------------
     361             :   // [Register Management]
     362             :   // --------------------------------------------------------------------------
     363             : 
     364             :   void _checkState();
     365             : 
     366             :   // --------------------------------------------------------------------------
     367             :   // [Attach / Detach]
     368             :   // --------------------------------------------------------------------------
     369             : 
     370             :   //! Attach.
     371             :   //!
     372             :   //! Attach a register to the 'VirtReg', changing 'VirtReg' members to show
     373             :   //! that the variable is currently alive and linking variable with the
     374             :   //! current 'X86RAState'.
     375             :   template<int C>
     376             :   ASMJIT_INLINE void attach(VirtReg* vreg, uint32_t physId, bool modified) {
     377             :     ASMJIT_ASSERT(vreg->getKind() == C);
     378             :     ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
     379             : 
     380             :     // Prevent Esp allocation if C==Gp.
     381             :     ASMJIT_ASSERT(C != X86Reg::kKindGp || physId != X86Gp::kIdSp);
     382             : 
     383             :     uint32_t regMask = Utils::mask(physId);
     384             : 
     385             :     vreg->setState(VirtReg::kStateReg);
     386             :     vreg->setModified(modified);
     387             :     vreg->setPhysId(physId);
     388             :     vreg->addHomeId(physId);
     389             : 
     390       23740 :     _x86State.getListByKind(C)[physId] = vreg;
     391             :     _x86State._occupied.or_(C, regMask);
     392             :     _x86State._modified.or_(C, static_cast<uint32_t>(modified) << physId);
     393             : 
     394             :     ASMJIT_X86_CHECK_STATE
     395       23740 :   }
     396             : 
     397             :   //! Detach.
     398             :   //!
     399             :   //! The opposite of 'Attach'. Detach resets the members in 'VirtReg'
     400             :   //! (physId, state and changed flags) and unlinks the variable with the
     401             :   //! current 'X86RAState'.
     402             :   template<int C>
     403             :   ASMJIT_INLINE void detach(VirtReg* vreg, uint32_t physId, uint32_t vState) {
     404             :     ASMJIT_ASSERT(vreg->getKind() == C);
     405             :     ASMJIT_ASSERT(vreg->getPhysId() == physId);
     406             :     ASMJIT_ASSERT(vState != VirtReg::kStateReg);
     407             : 
     408             :     uint32_t regMask = Utils::mask(physId);
     409             : 
     410             :     vreg->setState(vState);
     411             :     vreg->resetPhysId();
     412             :     vreg->setModified(false);
     413             : 
     414       26220 :     _x86State.getListByKind(C)[physId] = nullptr;
     415             :     _x86State._occupied.andNot(C, regMask);
     416             :     _x86State._modified.andNot(C, regMask);
     417             : 
     418             :     ASMJIT_X86_CHECK_STATE
     419       26220 :   }
     420             : 
     421             :   // --------------------------------------------------------------------------
     422             :   // [Rebase]
     423             :   // --------------------------------------------------------------------------
     424             : 
     425             :   //! Rebase.
     426             :   //!
     427             :   //! Change the register of the 'VirtReg' changing also the current 'X86RAState'.
     428             :   //! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't
     429             :   //! change the `VirtReg`s modified flag.
     430             :   template<int C>
     431             :   ASMJIT_INLINE void rebase(VirtReg* vreg, uint32_t newPhysId, uint32_t oldPhysId) {
     432             :     ASMJIT_ASSERT(vreg->getKind() == C);
     433             : 
     434             :     uint32_t newRegMask = Utils::mask(newPhysId);
     435             :     uint32_t oldRegMask = Utils::mask(oldPhysId);
     436         656 :     uint32_t bothRegMask = newRegMask ^ oldRegMask;
     437             : 
     438             :     vreg->setPhysId(newPhysId);
     439             : 
     440         656 :     _x86State.getListByKind(C)[oldPhysId] = nullptr;
     441         656 :     _x86State.getListByKind(C)[newPhysId] = vreg;
     442             : 
     443             :     _x86State._occupied.xor_(C, bothRegMask);
     444         656 :     _x86State._modified.xor_(C, bothRegMask & -static_cast<int32_t>(vreg->isModified()));
     445             : 
     446             :     ASMJIT_X86_CHECK_STATE
     447         656 :   }
     448             : 
     449             :   // --------------------------------------------------------------------------
     450             :   // [Load / Save]
     451             :   // --------------------------------------------------------------------------
     452             : 
     453             :   //! Load.
     454             :   //!
     455             :   //! Load variable from its memory slot to a register, emitting 'Load'
     456             :   //! instruction and changing the variable state to allocated.
     457             :   template<int C>
     458             :   ASMJIT_INLINE void load(VirtReg* vreg, uint32_t physId) {
     459             :     // Can be only called if variable is not allocated.
     460             :     ASMJIT_ASSERT(vreg->getKind() == C);
     461             :     ASMJIT_ASSERT(vreg->getState() != VirtReg::kStateReg);
     462             :     ASMJIT_ASSERT(vreg->getPhysId() == Globals::kInvalidRegId);
     463             : 
     464           0 :     emitLoad(vreg, physId, "Load");
     465             :     attach<C>(vreg, physId, false);
     466             : 
     467             :     ASMJIT_X86_CHECK_STATE
     468           0 :   }
     469             : 
     470             :   //! Save.
     471             :   //!
     472             :   //! Save the variable into its home location, but keep it as allocated.
     473             :   template<int C>
     474             :   ASMJIT_INLINE void save(VirtReg* vreg) {
     475             :     ASMJIT_ASSERT(vreg->getKind() == C);
     476             :     ASMJIT_ASSERT(vreg->getState() == VirtReg::kStateReg);
     477             :     ASMJIT_ASSERT(vreg->getPhysId() != Globals::kInvalidRegId);
     478             : 
     479             :     uint32_t physId = vreg->getPhysId();
     480             :     uint32_t regMask = Utils::mask(physId);
     481             : 
     482        3468 :     emitSave(vreg, physId, "Save");
     483             :     vreg->setModified(false);
     484             :     _x86State._modified.andNot(C, regMask);
     485             : 
     486             :     ASMJIT_X86_CHECK_STATE
     487        3468 :   }
     488             : 
     489             :   // --------------------------------------------------------------------------
     490             :   // [Move / Swap]
     491             :   // --------------------------------------------------------------------------
     492             : 
     493             :   //! Move a register.
     494             :   //!
     495             :   //! Move register from one index to another, emitting 'Move' if needed. This
     496             :   //! function does nothing if register is already at the given index.
     497             :   template<int C>
     498             :   ASMJIT_INLINE void move(VirtReg* vreg, uint32_t newPhysId) {
     499             :     ASMJIT_ASSERT(vreg->getKind() == C);
     500             :     ASMJIT_ASSERT(vreg->getState() == VirtReg::kStateReg);
     501             :     ASMJIT_ASSERT(vreg->getPhysId() != Globals::kInvalidRegId);
     502             : 
     503             :     uint32_t oldPhysId = vreg->getPhysId();
     504         656 :     if (newPhysId != oldPhysId) {
     505         656 :       emitMove(vreg, newPhysId, oldPhysId, "Move");
     506             :       rebase<C>(vreg, newPhysId, oldPhysId);
     507             :     }
     508             : 
     509             :     ASMJIT_X86_CHECK_STATE
     510             :   }
     511             : 
     512             :   //! Swap two registers
     513             :   //!
     514             :   //! It's only possible to swap Gp registers.
     515             :   ASMJIT_INLINE void swapGp(VirtReg* aVReg, VirtReg* bVReg) {
     516             :     ASMJIT_ASSERT(aVReg != bVReg);
     517             : 
     518             :     ASMJIT_ASSERT(aVReg->getKind() == X86Reg::kKindGp);
     519             :     ASMJIT_ASSERT(aVReg->getState() == VirtReg::kStateReg);
     520             :     ASMJIT_ASSERT(aVReg->getPhysId() != Globals::kInvalidRegId);
     521             : 
     522             :     ASMJIT_ASSERT(bVReg->getKind() == X86Reg::kKindGp);
     523             :     ASMJIT_ASSERT(bVReg->getState() == VirtReg::kStateReg);
     524             :     ASMJIT_ASSERT(bVReg->getPhysId() != Globals::kInvalidRegId);
     525             : 
     526             :     uint32_t aIndex = aVReg->getPhysId();
     527             :     uint32_t bIndex = bVReg->getPhysId();
     528             : 
     529           0 :     emitSwapGp(aVReg, bVReg, aIndex, bIndex, "Swap");
     530             : 
     531             :     aVReg->setPhysId(bIndex);
     532             :     bVReg->setPhysId(aIndex);
     533             : 
     534           0 :     _x86State.getListByKind(X86Reg::kKindGp)[aIndex] = bVReg;
     535           0 :     _x86State.getListByKind(X86Reg::kKindGp)[bIndex] = aVReg;
     536             : 
     537           0 :     uint32_t m = aVReg->isModified() ^ bVReg->isModified();
     538           0 :     _x86State._modified.xor_(X86Reg::kKindGp, (m << aIndex) | (m << bIndex));
     539             : 
     540             :     ASMJIT_X86_CHECK_STATE
     541             :   }
     542             : 
     543             :   // --------------------------------------------------------------------------
     544             :   // [Alloc / Spill]
     545             :   // --------------------------------------------------------------------------
     546             : 
     547             :   //! Alloc.
     548             :   template<int C>
     549             :   ASMJIT_INLINE void alloc(VirtReg* vreg, uint32_t physId) {
     550             :     ASMJIT_ASSERT(vreg->getKind() == C);
     551             :     ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
     552             : 
     553             :     uint32_t oldPhysId = vreg->getPhysId();
     554             :     uint32_t oldState = vreg->getState();
     555             :     uint32_t regMask = Utils::mask(physId);
     556             : 
     557             :     ASMJIT_ASSERT(_x86State.getListByKind(C)[physId] == nullptr || physId == oldPhysId);
     558             : 
     559        4424 :     if (oldState != VirtReg::kStateReg) {
     560        4424 :       if (oldState == VirtReg::kStateMem)
     561        4424 :         emitLoad(vreg, physId, "Alloc");
     562             :       vreg->setModified(false);
     563             :     }
     564           0 :     else if (oldPhysId != physId) {
     565           0 :       emitMove(vreg, physId, oldPhysId, "Alloc");
     566             : 
     567           0 :       _x86State.getListByKind(C)[oldPhysId] = nullptr;
     568           0 :       regMask ^= Utils::mask(oldPhysId);
     569             :     }
     570             :     else {
     571             :       ASMJIT_X86_CHECK_STATE
     572             :       return;
     573             :     }
     574             : 
     575             :     vreg->setState(VirtReg::kStateReg);
     576             :     vreg->setPhysId(physId);
     577             :     vreg->addHomeId(physId);
     578             : 
     579        4424 :     _x86State.getListByKind(C)[physId] = vreg;
     580             :     _x86State._occupied.xor_(C, regMask);
     581        4424 :     _x86State._modified.xor_(C, regMask & -static_cast<int32_t>(vreg->isModified()));
     582             : 
     583             :     ASMJIT_X86_CHECK_STATE
     584             :   }
     585             : 
     586             :   //! Spill.
     587             :   //!
     588             :   //! Spill variable/register, saves the content to the memory-home if modified.
     589             :   template<int C>
     590             :   ASMJIT_INLINE void spill(VirtReg* vreg) {
     591             :     ASMJIT_ASSERT(vreg->getKind() == C);
     592             : 
     593         548 :     if (vreg->getState() != VirtReg::kStateReg) {
     594             :       ASMJIT_X86_CHECK_STATE
     595             :       return;
     596             :     }
     597             : 
     598             :     uint32_t physId = vreg->getPhysId();
     599             :     ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
     600             :     ASMJIT_ASSERT(_x86State.getListByKind(C)[physId] == vreg);
     601             : 
     602         548 :     if (vreg->isModified())
     603         536 :       emitSave(vreg, physId, "Spill");
     604             :     detach<C>(vreg, physId, VirtReg::kStateMem);
     605             : 
     606             :     ASMJIT_X86_CHECK_STATE
     607             :   }
     608             : 
     609             :   // --------------------------------------------------------------------------
     610             :   // [Modify]
     611             :   // --------------------------------------------------------------------------
     612             : 
     613             :   template<int C>
     614             :   ASMJIT_INLINE void modify(VirtReg* vreg) {
     615             :     ASMJIT_ASSERT(vreg->getKind() == C);
     616             : 
     617             :     uint32_t physId = vreg->getPhysId();
     618             :     uint32_t regMask = Utils::mask(physId);
     619             : 
     620             :     vreg->setModified(true);
     621             :     _x86State._modified.or_(C, regMask);
     622             : 
     623             :     ASMJIT_X86_CHECK_STATE
     624             :   }
     625             : 
     626             :   // --------------------------------------------------------------------------
     627             :   // [Unuse]
     628             :   // --------------------------------------------------------------------------
     629             : 
     630             :   //! Unuse.
     631             :   //!
     632             :   //! Unuse variable, it will be detached it if it's allocated then its state
     633             :   //! will be changed to VirtReg::kStateNone.
     634             :   template<int C>
     635             :   ASMJIT_INLINE void unuse(VirtReg* vreg, uint32_t vState = VirtReg::kStateNone) {
     636             :     ASMJIT_ASSERT(vreg->getKind() == C);
     637             :     ASMJIT_ASSERT(vState != VirtReg::kStateReg);
     638             : 
     639             :     uint32_t physId = vreg->getPhysId();
     640       50366 :     if (physId != Globals::kInvalidRegId)
     641             :       detach<C>(vreg, physId, vState);
     642             :     else
     643             :       vreg->setState(vState);
     644             : 
     645             :     ASMJIT_X86_CHECK_STATE
     646             :   }
     647             : 
     648             :   // --------------------------------------------------------------------------
     649             :   // [State]
     650             :   // --------------------------------------------------------------------------
     651             : 
     652             :   //! Get state as `X86RAState`.
     653           0 :   ASMJIT_INLINE X86RAState* getState() const { return const_cast<X86RAState*>(&_x86State); }
     654             : 
     655             :   virtual void loadState(RAState* src) override;
     656             :   virtual RAState* saveState() override;
     657             : 
     658             :   virtual void switchState(RAState* src) override;
     659             :   virtual void intersectStates(RAState* a, RAState* b) override;
     660             : 
     661             :   // --------------------------------------------------------------------------
     662             :   // [Memory]
     663             :   // --------------------------------------------------------------------------
     664             : 
     665             :   ASMJIT_INLINE X86Mem getVarMem(VirtReg* vreg) {
     666        8428 :     (void)getVarCell(vreg);
     667             :     return X86Mem(Init,
     668             :       cc()->_nativeGpReg.getType(), vreg->getId(),
     669             :       Reg::kRegNone, kInvalidValue,
     670             :       0, 0, Mem::kSignatureMemRegHomeFlag);
     671             :   }
     672             : 
     673             :   // --------------------------------------------------------------------------
     674             :   // [Fetch]
     675             :   // --------------------------------------------------------------------------
     676             : 
     677             :   virtual Error fetch() override;
     678             : 
     679             :   // --------------------------------------------------------------------------
     680             :   // [Annotate]
     681             :   // --------------------------------------------------------------------------
     682             : 
     683             :   virtual Error annotate() override;
     684             : 
     685             :   // --------------------------------------------------------------------------
     686             :   // [Translate]
     687             :   // --------------------------------------------------------------------------
     688             : 
     689             :   virtual Error translate() override;
     690             : 
     691             :   // --------------------------------------------------------------------------
     692             :   // [Members]
     693             :   // --------------------------------------------------------------------------
     694             : 
     695             :   //! Count of X86/X64 registers.
     696             :   X86RegCount _regCount;
     697             :   //! X86/X64 stack-pointer (esp or rsp).
     698             :   X86Gp _zsp;
     699             :   //! X86/X64 frame-pointer (ebp or rbp).
     700             :   X86Gp _zbp;
     701             : 
     702             :   //! X86/X64 specific compiler state, linked to `_state`.
     703             :   X86RAState _x86State;
     704             :   //! Clobbered registers (for the whole function).
     705             :   X86RegMask _clobberedRegs;
     706             : 
     707             :   //! Global allocable registers mask.
     708             :   uint32_t _gaRegs[Globals::kMaxVRegKinds];
     709             : 
     710             :   bool _avxEnabled;
     711             : 
     712             :   //! Function variables base pointer (register).
     713             :   uint8_t _varBaseRegId;
     714             :   //! Function variables base offset.
     715             :   int32_t _varBaseOffset;
     716             : 
     717             :   //! Temporary string builder used for logging.
     718             :   StringBuilderTmp<256> _stringBuilder;
     719             : };
     720             : 
     721             : //! \}
     722             : 
     723             : } // asmjit namespace
     724             : } // namespace PLMD
     725             : 
     726             : // [Api-End]
     727             : #include "./asmjit_apiend.h"
     728             : 
     729             : // [Guard]
     730             : #endif // !ASMJIT_DISABLE_COMPILER
     731             : #endif // _ASMJIT_X86_X86REGALLOC_P_H
     732             : #pragma GCC diagnostic pop
     733             : #endif // __PLUMED_HAS_ASMJIT
     734             : #endif

Generated by: LCOV version 1.15