86#define DEBUG_TYPE "si-opt-vgpr-liverange"
114 void collectWaterfallCandidateRegisters(
126 void updateLiveRangeInElseRegion(
136 void optimizeWaterfallLiveRange(
146 return "SI Optimize VGPR LiveRange";
161 MachineFunctionProperties::Property::IsSSA);
166 MachineFunctionProperties::Property::NoPHIs);
177 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
178 return BR.getOperand(2).getMBB();
183void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
203 dbgs() <<
"Found Else blocks: ";
211void SIOptimizeVGPRLiveRange::findNonPHIUsesInBlock(
214 for (
auto &
UseMI :
MRI->use_nodbg_instructions(Reg)) {
222void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
229 for (
auto *Else : ElseBlocks) {
230 for (
auto &
MI :
Else->instrs()) {
231 if (
MI.isDebugInstr())
234 for (
auto &MO :
MI.operands()) {
235 if (!MO.isReg() || !MO.getReg() || MO.isDef())
249 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
250 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
254 if (!
VI.isLiveIn(*Endif, MOReg, *
MRI)) {
255 KillsInElse.
insert(MOReg);
258 <<
" as Live in Endif\n");
268 for (
auto &
MI :
Endif->phis()) {
269 for (
unsigned Idx = 1;
Idx <
MI.getNumOperands();
Idx += 2) {
270 auto &MO =
MI.getOperand(
Idx);
271 auto *Pred =
MI.getOperand(
Idx + 1).getMBB();
274 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
276 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
280 if (
Reg.isPhysical() || !
TRI->isVectorRegister(*
MRI, Reg))
285 if (
VI.isLiveIn(*Endif, Reg, *
MRI)) {
287 <<
" as Live in Endif\n");
294 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
295 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
301 for (
auto I =
MRI->use_nodbg_begin(Reg), E =
MRI->use_nodbg_end();
I != E;
305 auto *
UseMI =
I->getParent();
307 if (UseMBB ==
Flow || UseMBB == Endif) {
314 if ((UseMBB ==
Flow && IncomingMBB != If) ||
315 (UseMBB ==
Endif && IncomingMBB ==
Flow))
322 for (
auto Reg : KillsInElse) {
323 if (!IsLiveThroughThen(Reg))
330void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
337 auto *
MBB = LoopHeader;
340 for (
auto &
MI : *
MBB) {
341 if (
MI.isDebugInstr())
357 for (
auto *
I : Instructions) {
360 for (
auto &MO :
MI.all_uses()) {
379 if (!
Blocks.contains(Succ) &&
388 CandidateRegs.
insert(MOReg);
400void SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion(
407 while (!WorkList.empty()) {
408 auto *
MBB = WorkList.pop_back_val();
428 for (
auto I =
MRI->use_nodbg_begin(Reg), E =
MRI->use_nodbg_end();
I != E;
430 auto *
UseMI =
I->getParent();
440 findNonPHIUsesInBlock(Reg,
MBB,
Uses);
442 if (
Uses.size() == 1) {
445 LV->HandleVirtRegUse(Reg,
MBB, *(*
Uses.begin()));
446 }
else if (
Uses.size() > 1) {
452 LV->HandleVirtRegUse(Reg,
MBB,
MI);
458 LV->MarkVirtRegAliveInBlock(OldVarInfo,
MRI->getVRegDef(Reg)->getParent(),
463 for (
auto *
MI : OldVarInfo.
Kills) {
464 if (
Blocks.contains(
MI->getParent()))
465 MI->addRegisterKilled(Reg,
TRI);
469void SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion(
477 for (
auto *
MBB : ElseBlocks) {
488 auto I = OldVarInfo.
Kills.begin();
489 while (
I != OldVarInfo.
Kills.end()) {
490 if (ElseBlocks.contains((*I)->getParent())) {
491 NewVarInfo.
Kills.push_back(*
I);
499void SIOptimizeVGPRLiveRange::optimizeLiveRange(
506 const auto *RC =
MRI->getRegClass(Reg);
508 Register UndefReg =
MRI->createVirtualRegister(RC);
510 TII->get(TargetOpcode::PHI), NewReg);
511 for (
auto *Pred :
Flow->predecessors()) {
513 PHI.addReg(Reg).addMBB(Pred);
521 auto *
UseMI =
O.getParent();
524 if (UseBlock == Endif) {
548 updateLiveRangeInElseRegion(Reg, NewReg,
Flow, Endif, ElseBlocks);
549 updateLiveRangeInThenRegion(Reg, If,
Flow);
552void SIOptimizeVGPRLiveRange::optimizeWaterfallLiveRange(
558 const auto *RC =
MRI->getRegClass(Reg);
560 Register UndefReg =
MRI->createVirtualRegister(RC);
565 auto *
UseMI =
O.getParent();
568 if (
Blocks.contains(UseBlock))
574 TII->get(TargetOpcode::PHI), NewReg);
576 if (
Blocks.contains(Pred))
579 PHI.addReg(Reg).addMBB(Pred);
588 if (
MI->readsRegister(NewReg,
TRI)) {
589 MI->addRegisterKilled(NewReg,
TRI);
590 NewVarInfo.
Kills.push_back(
MI);
595 assert(Kill &&
"Failed to find last usage of register in loop");
598 bool PostKillBlock =
false;
600 auto BBNum =
Block->getNumber();
608 PostKillBlock |= (
Block == KillBlock);
611 }
else if (
Block != LoopHeader) {
617char SIOptimizeVGPRLiveRange::ID = 0;
620 "SI Optimize VGPR LiveRange",
false,
false)
630 return new SIOptimizeVGPRLiveRange();
633bool SIOptimizeVGPRLiveRange::runOnMachineFunction(
MachineFunction &MF) {
636 TII = ST.getInstrInfo();
637 TRI = &
TII->getRegisterInfo();
638 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
639 Loops = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
640 LV = &getAnalysis<LiveVariablesWrapperPass>().getLV();
646 bool MadeChange =
false;
653 if (
MI.getOpcode() == AMDGPU::SI_IF) {
655 auto *Endif = getElseTarget(IfTarget);
660 if (!MDT->dominates(&
MBB, IfTarget) || !MDT->dominates(IfTarget, Endif))
672 collectElseRegionBlocks(IfTarget, Endif, ElseBlocks);
675 collectCandidateRegisters(&
MBB, IfTarget, Endif, ElseBlocks,
677 MadeChange |= !CandidateRegs.
empty();
679 for (
auto Reg : CandidateRegs)
680 optimizeLiveRange(Reg, &
MBB, IfTarget, Endif, ElseBlocks);
681 }
else if (
MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP) {
682 auto *LoopHeader =
MI.getOperand(0).getMBB();
683 auto *LoopEnd = &
MBB;
692 collectWaterfallCandidateRegisters(LoopHeader, LoopEnd, CandidateRegs,
694 MadeChange |= !CandidateRegs.
empty();
696 for (
auto Reg : CandidateRegs)
697 optimizeWaterfallLiveRange(Reg, LoopHeader,
Blocks, Instructions);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
Provides AMDGPU specific target descriptions.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
Rewrite Partial Register Uses
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
This class represents the liveness of a register, stack slot, etc.
unsigned pred_size() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void push_back(MachineInstr *MI)
succ_iterator succ_begin()
unsigned succ_size() const
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
iterator_range< iterator > terminators()
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual MachineFunctionProperties getClearedProperties() const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
const MachineBasicBlock * getParent() const
bool isDebugInstr() const
const MachineOperand & getOperand(unsigned i) const
MachineBasicBlock * getMBB() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A vector that has set insertion semantics.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool contains(const key_type &key) const
Check if the SetVector contains the given key.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
StringRef - Represent a constant reference to a string, i.e.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BR
Control flow instructions. These all have token chains.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
char & SIOptimizeVGPRLiveRangeID
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
FunctionPass * createSIOptimizeVGPRLiveRangePass()
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
VarInfo - This represents the regions where a virtual register is live in the program.
std::vector< MachineInstr * > Kills
Kills - List of MachineInstruction's which are the last use of this virtual register (kill it) in the...
SparseBitVector AliveBlocks
AliveBlocks - Set of blocks in which this value is alive completely through.
bool isLiveIn(const MachineBasicBlock &MBB, Register Reg, MachineRegisterInfo &MRI)
isLiveIn - Is Reg live in to MBB? This means that Reg is live through MBB, or it is killed in MBB.