mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
ae65e281f3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
221 lines
6.8 KiB
C++
221 lines
6.8 KiB
C++
//===- GCNRegPressure.h -----------------------------------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
|
|
#define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
|
|
|
|
#include "AMDGPUSubtarget.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/CodeGen/LiveIntervals.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/SlotIndexes.h"
|
|
#include "llvm/MC/LaneBitmask.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include <algorithm>
|
|
#include <limits>
|
|
|
|
namespace llvm {
|
|
|
|
class MachineRegisterInfo;
|
|
class raw_ostream;
|
|
|
|
struct GCNRegPressure {
|
|
enum RegKind {
|
|
SGPR32,
|
|
SGPR_TUPLE,
|
|
VGPR32,
|
|
VGPR_TUPLE,
|
|
TOTAL_KINDS
|
|
};
|
|
|
|
GCNRegPressure() {
|
|
clear();
|
|
}
|
|
|
|
bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; }
|
|
|
|
void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); }
|
|
|
|
unsigned getSGPRNum() const { return Value[SGPR32]; }
|
|
unsigned getVGPRNum() const { return Value[VGPR32]; }
|
|
|
|
unsigned getVGPRTuplesWeight() const { return Value[VGPR_TUPLE]; }
|
|
unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; }
|
|
|
|
unsigned getOccupancy(const GCNSubtarget &ST) const {
|
|
return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()),
|
|
ST.getOccupancyWithNumVGPRs(getVGPRNum()));
|
|
}
|
|
|
|
void inc(unsigned Reg,
|
|
LaneBitmask PrevMask,
|
|
LaneBitmask NewMask,
|
|
const MachineRegisterInfo &MRI);
|
|
|
|
bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure& O) const {
|
|
return getOccupancy(ST) > O.getOccupancy(ST);
|
|
}
|
|
|
|
bool less(const GCNSubtarget &ST, const GCNRegPressure& O,
|
|
unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const;
|
|
|
|
bool operator==(const GCNRegPressure &O) const {
|
|
return std::equal(&Value[0], &Value[TOTAL_KINDS], O.Value);
|
|
}
|
|
|
|
bool operator!=(const GCNRegPressure &O) const {
|
|
return !(*this == O);
|
|
}
|
|
|
|
void print(raw_ostream &OS, const GCNSubtarget *ST = nullptr) const;
|
|
void dump() const { print(dbgs()); }
|
|
|
|
private:
|
|
unsigned Value[TOTAL_KINDS];
|
|
|
|
static unsigned getRegKind(unsigned Reg, const MachineRegisterInfo &MRI);
|
|
|
|
friend GCNRegPressure max(const GCNRegPressure &P1,
|
|
const GCNRegPressure &P2);
|
|
};
|
|
|
|
inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) {
|
|
GCNRegPressure Res;
|
|
for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; ++I)
|
|
Res.Value[I] = std::max(P1.Value[I], P2.Value[I]);
|
|
return Res;
|
|
}
|
|
|
|
class GCNRPTracker {
|
|
public:
|
|
using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
|
|
|
|
protected:
|
|
const LiveIntervals &LIS;
|
|
LiveRegSet LiveRegs;
|
|
GCNRegPressure CurPressure, MaxPressure;
|
|
const MachineInstr *LastTrackedMI = nullptr;
|
|
mutable const MachineRegisterInfo *MRI = nullptr;
|
|
|
|
GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
|
|
|
|
void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy,
|
|
bool After);
|
|
|
|
public:
|
|
// live regs for the current state
|
|
const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
|
|
const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
|
|
|
|
void clearMaxPressure() { MaxPressure.clear(); }
|
|
|
|
// returns MaxPressure, resetting it
|
|
decltype(MaxPressure) moveMaxPressure() {
|
|
auto Res = MaxPressure;
|
|
MaxPressure.clear();
|
|
return Res;
|
|
}
|
|
|
|
decltype(LiveRegs) moveLiveRegs() {
|
|
return std::move(LiveRegs);
|
|
}
|
|
|
|
static void printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
|
|
const MachineRegisterInfo &MRI);
|
|
};
|
|
|
|
class GCNUpwardRPTracker : public GCNRPTracker {
|
|
public:
|
|
GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
|
|
|
|
// reset tracker to the point just below MI
|
|
// filling live regs upon this point using LIS
|
|
void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
|
|
|
|
// move to the state just above the MI
|
|
void recede(const MachineInstr &MI);
|
|
|
|
// checks whether the tracker's state after receding MI corresponds
|
|
// to reported by LIS
|
|
bool isValid() const;
|
|
};
|
|
|
|
class GCNDownwardRPTracker : public GCNRPTracker {
|
|
// Last position of reset or advanceBeforeNext
|
|
MachineBasicBlock::const_iterator NextMI;
|
|
|
|
MachineBasicBlock::const_iterator MBBEnd;
|
|
|
|
public:
|
|
GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
|
|
|
|
const MachineBasicBlock::const_iterator getNext() const { return NextMI; }
|
|
|
|
// Reset tracker to the point before the MI
|
|
// filling live regs upon this point using LIS.
|
|
// Returns false if block is empty except debug values.
|
|
bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
|
|
|
|
// Move to the state right before the next MI. Returns false if reached
|
|
// end of the block.
|
|
bool advanceBeforeNext();
|
|
|
|
// Move to the state at the MI, advanceBeforeNext has to be called first.
|
|
void advanceToNext();
|
|
|
|
// Move to the state at the next MI. Returns false if reached end of block.
|
|
bool advance();
|
|
|
|
// Advance instructions until before End.
|
|
bool advance(MachineBasicBlock::const_iterator End);
|
|
|
|
// Reset to Begin and advance to End.
|
|
bool advance(MachineBasicBlock::const_iterator Begin,
|
|
MachineBasicBlock::const_iterator End,
|
|
const LiveRegSet *LiveRegsCopy = nullptr);
|
|
};
|
|
|
|
LaneBitmask getLiveLaneMask(unsigned Reg,
|
|
SlotIndex SI,
|
|
const LiveIntervals &LIS,
|
|
const MachineRegisterInfo &MRI);
|
|
|
|
GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI,
|
|
const LiveIntervals &LIS,
|
|
const MachineRegisterInfo &MRI);
|
|
|
|
inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
|
|
const LiveIntervals &LIS) {
|
|
return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS,
|
|
MI.getParent()->getParent()->getRegInfo());
|
|
}
|
|
|
|
inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
|
|
const LiveIntervals &LIS) {
|
|
return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS,
|
|
MI.getParent()->getParent()->getRegInfo());
|
|
}
|
|
|
|
template <typename Range>
|
|
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
|
|
Range &&LiveRegs) {
|
|
GCNRegPressure Res;
|
|
for (const auto &RM : LiveRegs)
|
|
Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI);
|
|
return Res;
|
|
}
|
|
|
|
void printLivesAt(SlotIndex SI,
|
|
const LiveIntervals &LIS,
|
|
const MachineRegisterInfo &MRI);
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
|