49#define DEBUG_TYPE "amdgpu-pre-ra-optimizations"
53 cl::desc(
"Enable register allocation anti-hints."),
58class GCNPreRAOptimizationsImpl {
79 GCNPreRAOptimizationsLegacy() : MachineFunctionPass(ID) {}
83 StringRef getPassName()
const override {
84 return "AMDGPU Pre-RA optimizations";
87 void getAnalysisUsage(AnalysisUsage &AU)
const override {
96 "AMDGPU Pre-RA optimizations",
false,
false)
101char GCNPreRAOptimizationsLegacy::ID = 0;
105bool GCNPreRAOptimizationsImpl::processReg(
Register Reg) {
111 bool IsAGPRDst =
TRI->isAGPRClass(MRI->getRegClass(Reg));
114 switch (I.getOpcode()) {
117 case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
127 Register SrcReg = I.getOperand(1).getReg();
129 if (!SrcReg.isVirtual())
133 bool IsAGPRSrc = TRI->isAGPRClass(MRI->getRegClass(SrcReg));
140 Register SrcSubReg = I.getOperand(1).getSubReg();
141 for (auto &Def : MRI->def_instructions(SrcReg)) {
142 if (SrcSubReg != Def.getOperand(0).getSubReg())
145 if (Def.getOpcode() == AMDGPU::V_ACCVGPR_WRITE_B32_e64) {
146 const MachineOperand &DefSrcMO = Def.getOperand(1);
151 if (DefSrcMO.isReg() && DefSrcMO.getReg().isVirtual()) {
153 I.getOperand(1).setReg(DefSrcMO.getReg());
154 I.getOperand(1).setSubReg(DefSrcMO.getSubReg());
158 ModifiedRegs.insert(DefSrcMO.getReg());
159 ModifiedRegs.insert(SrcReg);
170 case AMDGPU::S_MOV_B32:
171 if (I.getOperand(0).getReg() != Reg || !I.getOperand(1).isImm() ||
172 I.getNumOperands() != 2)
175 switch (I.getOperand(0).getSubReg()) {
182 Init |= Lo_32(I.getOperand(1).getImm());
188 Init |= static_cast<uint64_t>(I.getOperand(1).getImm()) << 32;
198 for (
Register RegToUpdate : ModifiedRegs) {
199 LIS->removeInterval(RegToUpdate);
200 LIS->createAndComputeVirtRegInterval(RegToUpdate);
208 if (!Def0 || !Def1 || Def0->getParent() != Def1->getParent())
215 LIS->getInstructionIndex(*Def0)))
218 LIS->RemoveMachineInstrFromMaps(*Def0);
219 LIS->RemoveMachineInstrFromMaps(*Def1);
220 auto NewI =
BuildMI(*Def0->getParent(), *Def0, Def0->getDebugLoc(),
221 TII->get(AMDGPU::S_MOV_B64_IMM_PSEUDO),
Reg)
224 Def0->eraseFromParent();
225 Def1->eraseFromParent();
226 LIS->InsertMachineInstrInMaps(*NewI);
227 LIS->removeInterval(
Reg);
228 LIS->createAndComputeVirtRegInterval(
Reg);
235bool GCNPreRAOptimizationsLegacy::runOnMachineFunction(
MachineFunction &MF) {
238 LiveIntervals *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
239 return GCNPreRAOptimizationsImpl(LIS).run(MF);
246 GCNPreRAOptimizationsImpl(LIS).
run(MF);
250void GCNPreRAOptimizationsImpl::hintTrue16Copy(
const MachineInstr &
MI) {
254 bool IsDst16Bit = AMDGPU::VGPR_16RegClass.hasSubClassEq(DstRC);
255 if (Dst.isVirtual() && IsDst16Bit && Src.isPhysical() &&
256 TRI->getRegClassForReg(*MRI, Src) == &AMDGPU::VGPR_32RegClass)
258 if (Src.isVirtual() && MRI->
getRegClass(Src) == &AMDGPU::VGPR_16RegClass &&
259 Dst.isPhysical() && DstRC == &AMDGPU::VGPR_32RegClass)
261 if (!Dst.isVirtual() || !Src.isVirtual())
263 if (MRI->
getRegClass(Dst) == &AMDGPU::VGPR_32RegClass &&
264 MRI->
getRegClass(Src) == &AMDGPU::VGPR_16RegClass) {
268 if (IsDst16Bit && MRI->
getRegClass(Src) == &AMDGPU::VGPR_32RegClass)
272bool GCNPreRAOptimizationsImpl::optimizeBVHStack(MachineInstr &
MI) {
276 auto CheckUse = [&](MachineOperand &
Use) {
282 const AMDGPU::MIMGBaseOpcodeInfo *BaseInfo =
290 CheckUse(*
TII->getNamedOperand(
MI, AMDGPU::OpName::data0));
291 CheckUse(*
TII->getNamedOperand(
MI, AMDGPU::OpName::data1));
311 TII =
ST.getInstrInfo();
313 TRI =
ST.getRegisterInfo();
318 SchedModel.
init(&ST);
319 AMDGPU::HazardContext HCtx{
TII,
TRI, MRI, LIS, &
ST, &SchedModel};
331 (
ST.hasGFX90AInsts() || !
TRI->isAGPRClass(RC)))
337 const bool HasBVHStack =
ST.hasBVHDualAndBVH8Insts();
338 const bool HasRealTrue16 =
ST.useRealTrue16Insts();
340 if (!HasRealTrue16 && !HasBVHStack)
343 for (MachineBasicBlock &
MBB : MF) {
344 for (MachineInstr &
MI :
MBB) {
346 if (HasRealTrue16 &&
MI.getOpcode() == AMDGPU::COPY) {
352 (
MI.getOpcode() == AMDGPU::DS_BVH_STACK_RTN_B32 ||
353 MI.getOpcode() == AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32 ||
354 MI.getOpcode() == AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64)) {
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
Provides AMDGPU specific target descriptions.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< bool > EnableAntiHints("amdgpu-anti-hints", cl::Hidden, cl::desc("Enable register allocation anti-hints."), cl::init(true))
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
bool hasInterval(Register Reg) const
void removeInterval(Register Reg)
Interval removal.
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
unsigned getSizeInBits() const
Return the size of the physical register in bits if we are able to determine it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< def_instr_iterator > def_instructions(Register Reg) const
void setRegAllocationHint(Register VReg, unsigned Type, Register PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register.
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
static bool isImage(const MachineInstr &MI)
static bool isEarlierInstr(SlotIndex A, SlotIndex B)
isEarlierInstr - Return true if A refers to an instruction earlier than B.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
void push_back(const T &Elt)
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
void applyAntiHintRules(MachineFunction &MF, const HazardContext &Ctx)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
char & GCNPreRAOptimizationsID
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.