87#define DEBUG_TYPE "si-opt-vgpr-liverange"
91class SIOptimizeVGPRLiveRange {
118 void collectWaterfallCandidateRegisters(
130 void updateLiveRangeInElseRegion(
140 void optimizeWaterfallLiveRange(
155 return "SI Optimize VGPR LiveRange";
185 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
186 return BR.getOperand(2).getMBB();
191void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
211 dbgs() <<
"Found Else blocks: ";
219void SIOptimizeVGPRLiveRange::findNonPHIUsesInBlock(
222 for (
auto &
UseMI :
MRI->use_nodbg_instructions(Reg)) {
230void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
237 for (
auto *Else : ElseBlocks) {
238 for (
auto &
MI :
Else->instrs()) {
239 if (
MI.isDebugInstr())
242 for (
auto &MO :
MI.operands()) {
243 if (!MO.isReg() || !MO.getReg() || MO.isDef())
257 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
258 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
262 if (!
VI.isLiveIn(*Endif, MOReg, *
MRI)) {
263 KillsInElse.
insert(MOReg);
266 <<
" as Live in Endif\n");
276 for (
auto &
MI :
Endif->phis()) {
277 for (
unsigned Idx = 1;
Idx <
MI.getNumOperands();
Idx += 2) {
278 auto &MO =
MI.getOperand(
Idx);
279 auto *Pred =
MI.getOperand(
Idx + 1).getMBB();
282 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
284 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
288 if (
Reg.isPhysical() || !
TRI->isVectorRegister(*
MRI, Reg))
293 if (
VI.isLiveIn(*Endif, Reg, *
MRI)) {
295 <<
" as Live in Endif\n");
302 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
303 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
309 for (
auto I =
MRI->use_nodbg_begin(Reg), E =
MRI->use_nodbg_end();
I != E;
313 auto *
UseMI =
I->getParent();
315 if (UseMBB ==
Flow || UseMBB == Endif) {
322 if ((UseMBB ==
Flow && IncomingMBB != If) ||
323 (UseMBB ==
Endif && IncomingMBB ==
Flow))
330 for (
auto Reg : KillsInElse) {
331 if (!IsLiveThroughThen(Reg))
338void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
345 auto *
MBB = LoopHeader;
348 for (
auto &
MI : *
MBB) {
349 if (
MI.isDebugInstr())
365 for (
auto *
I : Instructions) {
368 for (
auto &MO :
MI.all_uses()) {
387 if (!
Blocks.contains(Succ) &&
396 CandidateRegs.
insert(MOReg);
408void SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion(
415 while (!WorkList.empty()) {
416 auto *
MBB = WorkList.pop_back_val();
434 for (
auto I =
MRI->use_nodbg_begin(Reg), E =
MRI->use_nodbg_end();
I != E;
436 auto *
UseMI =
I->getParent();
446 findNonPHIUsesInBlock(Reg,
MBB,
Uses);
448 if (
Uses.size() == 1) {
451 LV->HandleVirtRegUse(Reg,
MBB, *(*
Uses.begin()));
452 }
else if (
Uses.size() > 1) {
458 LV->HandleVirtRegUse(Reg,
MBB,
MI);
464 LV->MarkVirtRegAliveInBlock(OldVarInfo,
MRI->getVRegDef(Reg)->getParent(),
469 for (
auto *
MI : OldVarInfo.
Kills) {
470 if (
Blocks.contains(
MI->getParent()))
471 MI->addRegisterKilled(Reg,
TRI);
475void SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion(
483 for (
auto *
MBB : ElseBlocks) {
494 auto I = OldVarInfo.
Kills.begin();
495 while (
I != OldVarInfo.
Kills.end()) {
496 if (ElseBlocks.contains((*I)->getParent())) {
497 NewVarInfo.
Kills.push_back(*
I);
505void SIOptimizeVGPRLiveRange::optimizeLiveRange(
512 const auto *RC =
MRI->getRegClass(Reg);
514 Register UndefReg =
MRI->createVirtualRegister(RC);
516 TII->get(TargetOpcode::PHI), NewReg);
517 for (
auto *Pred :
Flow->predecessors()) {
519 PHI.addReg(Reg).addMBB(Pred);
527 auto *
UseMI =
O.getParent();
530 if (UseBlock == Endif) {
554 updateLiveRangeInElseRegion(Reg, NewReg,
Flow, Endif, ElseBlocks);
555 updateLiveRangeInThenRegion(Reg, If,
Flow);
558void SIOptimizeVGPRLiveRange::optimizeWaterfallLiveRange(
564 const auto *RC =
MRI->getRegClass(Reg);
566 Register UndefReg =
MRI->createVirtualRegister(RC);
571 auto *
UseMI =
O.getParent();
574 if (
Blocks.contains(UseBlock))
580 TII->get(TargetOpcode::PHI), NewReg);
582 if (
Blocks.contains(Pred))
585 PHI.addReg(Reg).addMBB(Pred);
594 if (
MI->readsRegister(NewReg,
TRI)) {
595 MI->addRegisterKilled(NewReg,
TRI);
596 NewVarInfo.
Kills.push_back(
MI);
601 assert(Kill &&
"Failed to find last usage of register in loop");
604 bool PostKillBlock =
false;
606 auto BBNum =
Block->getNumber();
614 PostKillBlock |= (
Block == KillBlock);
617 }
else if (
Block != LoopHeader) {
623char SIOptimizeVGPRLiveRangeLegacy::ID = 0;
626 "SI Optimize VGPR LiveRange",
false,
false)
636 return new SIOptimizeVGPRLiveRangeLegacy();
639bool SIOptimizeVGPRLiveRangeLegacy::runOnMachineFunction(
MachineFunction &MF) {
643 LiveVariables *LV = &getAnalysis<LiveVariablesWrapperPass>().getLV();
645 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
647 return SIOptimizeVGPRLiveRange(LV, MDT,
Loops).run(MF);
658 bool Changed = SIOptimizeVGPRLiveRange(LV, MDT,
Loops).
run(MF);
672 TII = ST.getInstrInfo();
673 TRI = &
TII->getRegisterInfo();
676 bool MadeChange =
false;
683 if (
MI.getOpcode() == AMDGPU::SI_IF) {
685 auto *Endif = getElseTarget(IfTarget);
702 collectElseRegionBlocks(IfTarget, Endif, ElseBlocks);
705 collectCandidateRegisters(&
MBB, IfTarget, Endif, ElseBlocks,
707 MadeChange |= !CandidateRegs.
empty();
709 for (
auto Reg : CandidateRegs)
710 optimizeLiveRange(Reg, &
MBB, IfTarget, Endif, ElseBlocks);
711 }
else if (
MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP) {
712 auto *LoopHeader =
MI.getOperand(0).getMBB();
713 auto *LoopEnd = &
MBB;
722 collectWaterfallCandidateRegisters(LoopHeader, LoopEnd, CandidateRegs,
724 MadeChange |= !CandidateRegs.
empty();
726 for (
auto Reg : CandidateRegs)
727 optimizeWaterfallLiveRange(Reg, LoopHeader,
Blocks, Instructions);
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Register 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)
Remove Loads Into Fake Uses
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
Analysis pass which computes a DominatorTree.
FunctionPass class - This class is used to implement most global optimizations.
This class represents the liveness of a register, stack slot, etc.
An RAII based helper class to modify MachineFunctionProperties when running pass.
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
LLVM_ABI 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.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
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.
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
Analysis pass that exposes the MachineLoopInfo for a machine function.
LLVM_ABI Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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...
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
char & SIOptimizeVGPRLiveRangeLegacyID
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createSIOptimizeVGPRLiveRangeLegacyPass()
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI 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.