diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h')
-rw-r--r-- | contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h b/contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h new file mode 100644 index 0000000000..11702d47e2 --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/CodeGen/RegisterPressure.h @@ -0,0 +1,585 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the RegisterPressure class which can be used to track +// MachineInstr level register pressure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTERPRESSURE_H +#define LLVM_CODEGEN_REGISTERPRESSURE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/MC/LaneBitmask.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <limits> +#include <vector> + +namespace llvm { + +class LiveIntervals; +class MachineFunction; +class MachineInstr; +class MachineRegisterInfo; +class RegisterClassInfo; + +struct RegisterMaskPair { + Register RegUnit; ///< Virtual register or register unit. + LaneBitmask LaneMask; + + RegisterMaskPair(Register RegUnit, LaneBitmask LaneMask) + : RegUnit(RegUnit), LaneMask(LaneMask) {} +}; + +/// Base class for register pressure results. +struct RegisterPressure { + /// Map of max reg pressure indexed by pressure set ID, not class ID. + std::vector<unsigned> MaxSetPressure; + + /// List of live in virtual registers or physical register units. + SmallVector<RegisterMaskPair,8> LiveInRegs; + SmallVector<RegisterMaskPair,8> LiveOutRegs; + + void dump(const TargetRegisterInfo *TRI) const; +}; + +/// RegisterPressure computed within a region of instructions delimited by +/// TopIdx and BottomIdx. During pressure computation, the maximum pressure per +/// register pressure set is increased. Once pressure within a region is fully +/// computed, the live-in and live-out sets are recorded. +/// +/// This is preferable to RegionPressure when LiveIntervals are available, +/// because delimiting regions by SlotIndex is more robust and convenient than +/// holding block iterators. The block contents can change without invalidating +/// the pressure result. +struct IntervalPressure : RegisterPressure { + /// Record the boundary of the region being tracked. + SlotIndex TopIdx; + SlotIndex BottomIdx; + + void reset(); + + void openTop(SlotIndex NextTop); + + void openBottom(SlotIndex PrevBottom); +}; + +/// RegisterPressure computed within a region of instructions delimited by +/// TopPos and BottomPos. This is a less precise version of IntervalPressure for +/// use when LiveIntervals are unavailable. +struct RegionPressure : RegisterPressure { + /// Record the boundary of the region being tracked. + MachineBasicBlock::const_iterator TopPos; + MachineBasicBlock::const_iterator BottomPos; + + void reset(); + + void openTop(MachineBasicBlock::const_iterator PrevTop); + + void openBottom(MachineBasicBlock::const_iterator PrevBottom); +}; + +/// Capture a change in pressure for a single pressure set. UnitInc may be +/// expressed in terms of upward or downward pressure depending on the client +/// and will be dynamically adjusted for current liveness. +/// +/// Pressure increments are tiny, typically 1-2 units, and this is only for +/// heuristics, so we don't check UnitInc overflow. Instead, we may have a +/// higher level assert that pressure is consistent within a region. We also +/// effectively ignore dead defs which don't affect heuristics much. +class PressureChange { + uint16_t PSetID = 0; // ID+1. 0=Invalid. + int16_t UnitInc = 0; + +public: + PressureChange() = default; + PressureChange(unsigned id): PSetID(id + 1) { + assert(id < std::numeric_limits<uint16_t>::max() && "PSetID overflow."); + } + + bool isValid() const { return PSetID > 0; } + + unsigned getPSet() const { + assert(isValid() && "invalid PressureChange"); + return PSetID - 1; + } + + // If PSetID is invalid, return UINT16_MAX to give it lowest priority. + unsigned getPSetOrMax() const { + return (PSetID - 1) & std::numeric_limits<uint16_t>::max(); + } + + int getUnitInc() const { return UnitInc; } + + void setUnitInc(int Inc) { UnitInc = Inc; } + + bool operator==(const PressureChange &RHS) const { + return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; + } + + void dump() const; +}; + +/// List of PressureChanges in order of increasing, unique PSetID. +/// +/// Use a small fixed number, because we can fit more PressureChanges in an +/// empty SmallVector than ever need to be tracked per register class. If more +/// PSets are affected, then we only track the most constrained. +class PressureDiff { + // The initial design was for MaxPSets=4, but that requires PSet partitions, + // which are not yet implemented. (PSet partitions are equivalent PSets given + // the register classes actually in use within the scheduling region.) + enum { MaxPSets = 16 }; + + PressureChange PressureChanges[MaxPSets]; + + using iterator = PressureChange *; + + iterator nonconst_begin() { return &PressureChanges[0]; } + iterator nonconst_end() { return &PressureChanges[MaxPSets]; } + +public: + using const_iterator = const PressureChange *; + + const_iterator begin() const { return &PressureChanges[0]; } + const_iterator end() const { return &PressureChanges[MaxPSets]; } + + void addPressureChange(Register RegUnit, bool IsDec, + const MachineRegisterInfo *MRI); + + void dump(const TargetRegisterInfo &TRI) const; +}; + +/// List of registers defined and used by a machine instruction. +class RegisterOperands { +public: + /// List of virtual registers and register units read by the instruction. + SmallVector<RegisterMaskPair, 8> Uses; + /// List of virtual registers and register units defined by the + /// instruction which are not dead. + SmallVector<RegisterMaskPair, 8> Defs; + /// List of virtual registers and register units defined by the + /// instruction but dead. + SmallVector<RegisterMaskPair, 8> DeadDefs; + + /// Analyze the given instruction \p MI and fill in the Uses, Defs and + /// DeadDefs list based on the MachineOperand flags. + void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, + const MachineRegisterInfo &MRI, bool TrackLaneMasks, + bool IgnoreDead); + + /// Use liveness information to find dead defs not marked with a dead flag + /// and move them to the DeadDefs vector. + void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS); + + /// Use liveness information to find out which uses/defs are partially + /// undefined/dead and adjust the RegisterMaskPairs accordingly. + /// If \p AddFlagsMI is given then missing read-undef and dead flags will be + /// added to the instruction. + void adjustLaneLiveness(const LiveIntervals &LIS, + const MachineRegisterInfo &MRI, SlotIndex Pos, + MachineInstr *AddFlagsMI = nullptr); +}; + +/// Array of PressureDiffs. +class PressureDiffs { + PressureDiff *PDiffArray = nullptr; + unsigned Size = 0; + unsigned Max = 0; + +public: + PressureDiffs() = default; + ~PressureDiffs() { free(PDiffArray); } + + void clear() { Size = 0; } + + void init(unsigned N); + + PressureDiff &operator[](unsigned Idx) { + assert(Idx < Size && "PressureDiff index out of bounds"); + return PDiffArray[Idx]; + } + const PressureDiff &operator[](unsigned Idx) const { + return const_cast<PressureDiffs*>(this)->operator[](Idx); + } + + /// Record pressure difference induced by the given operand list to + /// node with index \p Idx. + void addInstruction(unsigned Idx, const RegisterOperands &RegOpers, + const MachineRegisterInfo &MRI); +}; + +/// Store the effects of a change in pressure on things that MI scheduler cares +/// about. +/// +/// Excess records the value of the largest difference in register units beyond +/// the target's pressure limits across the affected pressure sets, where +/// largest is defined as the absolute value of the difference. Negative +/// ExcessUnits indicates a reduction in pressure that had already exceeded the +/// target's limits. +/// +/// CriticalMax records the largest increase in the tracker's max pressure that +/// exceeds the critical limit for some pressure set determined by the client. +/// +/// CurrentMax records the largest increase in the tracker's max pressure that +/// exceeds the current limit for some pressure set determined by the client. +struct RegPressureDelta { + PressureChange Excess; + PressureChange CriticalMax; + PressureChange CurrentMax; + + RegPressureDelta() = default; + + bool operator==(const RegPressureDelta &RHS) const { + return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax + && CurrentMax == RHS.CurrentMax; + } + bool operator!=(const RegPressureDelta &RHS) const { + return !operator==(RHS); + } + void dump() const; +}; + +/// A set of live virtual registers and physical register units. +/// +/// This is a wrapper around a SparseSet which deals with mapping register unit +/// and virtual register indexes to an index usable by the sparse set. +class LiveRegSet { +private: + struct IndexMaskPair { + unsigned Index; + LaneBitmask LaneMask; + + IndexMaskPair(unsigned Index, LaneBitmask LaneMask) + : Index(Index), LaneMask(LaneMask) {} + + unsigned getSparseSetIndex() const { + return Index; + } + }; + + using RegSet = SparseSet<IndexMaskPair>; + RegSet Regs; + unsigned NumRegUnits; + + unsigned getSparseIndexFromReg(Register Reg) const { + if (Reg.isVirtual()) + return Register::virtReg2Index(Reg) + NumRegUnits; + assert(Reg < NumRegUnits); + return Reg; + } + + Register getRegFromSparseIndex(unsigned SparseIndex) const { + if (SparseIndex >= NumRegUnits) + return Register::index2VirtReg(SparseIndex - NumRegUnits); + return Register(SparseIndex); + } + +public: + void clear(); + void init(const MachineRegisterInfo &MRI); + + LaneBitmask contains(Register Reg) const { + unsigned SparseIndex = getSparseIndexFromReg(Reg); + RegSet::const_iterator I = Regs.find(SparseIndex); + if (I == Regs.end()) + return LaneBitmask::getNone(); + return I->LaneMask; + } + + /// Mark the \p Pair.LaneMask lanes of \p Pair.Reg as live. + /// Returns the previously live lanes of \p Pair.Reg. + LaneBitmask insert(RegisterMaskPair Pair) { + unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit); + auto InsertRes = Regs.insert(IndexMaskPair(SparseIndex, Pair.LaneMask)); + if (!InsertRes.second) { + LaneBitmask PrevMask = InsertRes.first->LaneMask; + InsertRes.first->LaneMask |= Pair.LaneMask; + return PrevMask; + } + return LaneBitmask::getNone(); + } + + /// Clears the \p Pair.LaneMask lanes of \p Pair.Reg (mark them as dead). + /// Returns the previously live lanes of \p Pair.Reg. + LaneBitmask erase(RegisterMaskPair Pair) { + unsigned SparseIndex = getSparseIndexFromReg(Pair.RegUnit); + RegSet::iterator I = Regs.find(SparseIndex); + if (I == Regs.end()) + return LaneBitmask::getNone(); + LaneBitmask PrevMask = I->LaneMask; + I->LaneMask &= ~Pair.LaneMask; + return PrevMask; + } + + size_t size() const { + return Regs.size(); + } + + template<typename ContainerT> + void appendTo(ContainerT &To) const { + for (const IndexMaskPair &P : Regs) { + Register Reg = getRegFromSparseIndex(P.Index); + if (P.LaneMask.any()) + To.push_back(RegisterMaskPair(Reg, P.LaneMask)); + } + } +}; + +/// Track the current register pressure at some position in the instruction +/// stream, and remember the high water mark within the region traversed. This +/// does not automatically consider live-through ranges. The client may +/// independently adjust for global liveness. +/// +/// Each RegPressureTracker only works within a MachineBasicBlock. Pressure can +/// be tracked across a larger region by storing a RegisterPressure result at +/// each block boundary and explicitly adjusting pressure to account for block +/// live-in and live-out register sets. +/// +/// RegPressureTracker holds a reference to a RegisterPressure result that it +/// computes incrementally. During downward tracking, P.BottomIdx or P.BottomPos +/// is invalid until it reaches the end of the block or closeRegion() is +/// explicitly called. Similarly, P.TopIdx is invalid during upward +/// tracking. Changing direction has the side effect of closing region, and +/// traversing past TopIdx or BottomIdx reopens it. +class RegPressureTracker { + const MachineFunction *MF = nullptr; + const TargetRegisterInfo *TRI = nullptr; + const RegisterClassInfo *RCI = nullptr; + const MachineRegisterInfo *MRI; + const LiveIntervals *LIS = nullptr; + + /// We currently only allow pressure tracking within a block. + const MachineBasicBlock *MBB = nullptr; + + /// Track the max pressure within the region traversed so far. + RegisterPressure &P; + + /// Run in two modes dependending on whether constructed with IntervalPressure + /// or RegisterPressure. If requireIntervals is false, LIS are ignored. + bool RequireIntervals; + + /// True if UntiedDefs will be populated. + bool TrackUntiedDefs = false; + + /// True if lanemasks should be tracked. + bool TrackLaneMasks = false; + + /// Register pressure corresponds to liveness before this instruction + /// iterator. It may point to the end of the block or a DebugValue rather than + /// an instruction. + MachineBasicBlock::const_iterator CurrPos; + + /// Pressure map indexed by pressure set ID, not class ID. + std::vector<unsigned> CurrSetPressure; + + /// Set of live registers. + LiveRegSet LiveRegs; + + /// Set of vreg defs that start a live range. + SparseSet<Register, VirtReg2IndexFunctor> UntiedDefs; + /// Live-through pressure. + std::vector<unsigned> LiveThruPressure; + +public: + RegPressureTracker(IntervalPressure &rp) : P(rp), RequireIntervals(true) {} + RegPressureTracker(RegionPressure &rp) : P(rp), RequireIntervals(false) {} + + void reset(); + + void init(const MachineFunction *mf, const RegisterClassInfo *rci, + const LiveIntervals *lis, const MachineBasicBlock *mbb, + MachineBasicBlock::const_iterator pos, + bool TrackLaneMasks, bool TrackUntiedDefs); + + /// Force liveness of virtual registers or physical register + /// units. Particularly useful to initialize the livein/out state of the + /// tracker before the first call to advance/recede. + void addLiveRegs(ArrayRef<RegisterMaskPair> Regs); + + /// Get the MI position corresponding to this register pressure. + MachineBasicBlock::const_iterator getPos() const { return CurrPos; } + + // Reset the MI position corresponding to the register pressure. This allows + // schedulers to move instructions above the RegPressureTracker's + // CurrPos. Since the pressure is computed before CurrPos, the iterator + // position changes while pressure does not. + void setPos(MachineBasicBlock::const_iterator Pos) { CurrPos = Pos; } + + /// Recede across the previous instruction. + void recede(SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr); + + /// Recede across the previous instruction. + /// This "low-level" variant assumes that recedeSkipDebugValues() was + /// called previously and takes precomputed RegisterOperands for the + /// instruction. + void recede(const RegisterOperands &RegOpers, + SmallVectorImpl<RegisterMaskPair> *LiveUses = nullptr); + + /// Recede until we find an instruction which is not a DebugValue. + void recedeSkipDebugValues(); + + /// Advance across the current instruction. + void advance(); + + /// Advance across the current instruction. + /// This is a "low-level" variant of advance() which takes precomputed + /// RegisterOperands of the instruction. + void advance(const RegisterOperands &RegOpers); + + /// Finalize the region boundaries and recored live ins and live outs. + void closeRegion(); + + /// Initialize the LiveThru pressure set based on the untied defs found in + /// RPTracker. + void initLiveThru(const RegPressureTracker &RPTracker); + + /// Copy an existing live thru pressure result. + void initLiveThru(ArrayRef<unsigned> PressureSet) { + LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); + } + + ArrayRef<unsigned> getLiveThru() const { return LiveThruPressure; } + + /// Get the resulting register pressure over the traversed region. + /// This result is complete if closeRegion() was explicitly invoked. + RegisterPressure &getPressure() { return P; } + const RegisterPressure &getPressure() const { return P; } + + /// Get the register set pressure at the current position, which may be less + /// than the pressure across the traversed region. + const std::vector<unsigned> &getRegSetPressureAtPos() const { + return CurrSetPressure; + } + + bool isTopClosed() const; + bool isBottomClosed() const; + + void closeTop(); + void closeBottom(); + + /// Consider the pressure increase caused by traversing this instruction + /// bottom-up. Find the pressure set with the most change beyond its pressure + /// limit based on the tracker's current pressure, and record the number of + /// excess register units of that pressure set introduced by this instruction. + void getMaxUpwardPressureDelta(const MachineInstr *MI, + PressureDiff *PDiff, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit); + + void getUpwardPressureDelta(const MachineInstr *MI, + /*const*/ PressureDiff &PDiff, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit) const; + + /// Consider the pressure increase caused by traversing this instruction + /// top-down. Find the pressure set with the most change beyond its pressure + /// limit based on the tracker's current pressure, and record the number of + /// excess register units of that pressure set introduced by this instruction. + void getMaxDownwardPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit); + + /// Find the pressure set with the most change beyond its pressure limit after + /// traversing this instruction either upward or downward depending on the + /// closed end of the current region. + void getMaxPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef<PressureChange> CriticalPSets, + ArrayRef<unsigned> MaxPressureLimit) { + if (isTopClosed()) + return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, + MaxPressureLimit); + + assert(isBottomClosed() && "Uninitialized pressure tracker"); + return getMaxUpwardPressureDelta(MI, nullptr, Delta, CriticalPSets, + MaxPressureLimit); + } + + /// Get the pressure of each PSet after traversing this instruction bottom-up. + void getUpwardPressure(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult); + + /// Get the pressure of each PSet after traversing this instruction top-down. + void getDownwardPressure(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult); + + void getPressureAfterInst(const MachineInstr *MI, + std::vector<unsigned> &PressureResult, + std::vector<unsigned> &MaxPressureResult) { + if (isTopClosed()) + return getUpwardPressure(MI, PressureResult, MaxPressureResult); + + assert(isBottomClosed() && "Uninitialized pressure tracker"); + return getDownwardPressure(MI, PressureResult, MaxPressureResult); + } + + bool hasUntiedDef(Register VirtReg) const { + return UntiedDefs.count(VirtReg); + } + + void dump() const; + +protected: + /// Add Reg to the live out set and increase max pressure. + void discoverLiveOut(RegisterMaskPair Pair); + /// Add Reg to the live in set and increase max pressure. + void discoverLiveIn(RegisterMaskPair Pair); + + /// Get the SlotIndex for the first nondebug instruction including or + /// after the current position. + SlotIndex getCurrSlot() const; + + void increaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, + LaneBitmask NewMask); + void decreaseRegPressure(Register RegUnit, LaneBitmask PreviousMask, + LaneBitmask NewMask); + + void bumpDeadDefs(ArrayRef<RegisterMaskPair> DeadDefs); + + void bumpUpwardPressure(const MachineInstr *MI); + void bumpDownwardPressure(const MachineInstr *MI); + + void discoverLiveInOrOut(RegisterMaskPair Pair, + SmallVectorImpl<RegisterMaskPair> &LiveInOrOut); + + LaneBitmask getLastUsedLanes(Register RegUnit, SlotIndex Pos) const; + LaneBitmask getLiveLanesAt(Register RegUnit, SlotIndex Pos) const; + LaneBitmask getLiveThroughAt(Register RegUnit, SlotIndex Pos) const; +}; + +void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, + const TargetRegisterInfo *TRI); + +} // end namespace llvm + +#endif // LLVM_CODEGEN_REGISTERPRESSURE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |