89#define DEBUG_TYPE "si-opt-vgpr-liverange"
93class SIOptimizeVGPRLiveRange {
120 void collectWaterfallCandidateRegisters(
132 void updateLiveRangeInElseRegion(
142 void optimizeWaterfallLiveRange(
157 return "SI Optimize VGPR LiveRange";
188 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
189 return BR.getOperand(2).getMBB();
194void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
195 MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
196 SmallSetVector<MachineBasicBlock *, 16> &Blocks)
const {
207 if (Cur < Blocks.
size())
214 dbgs() <<
"Found Else blocks: ";
215 for (
auto *
MBB : Blocks)
222void SIOptimizeVGPRLiveRange::findNonPHIUsesInBlock(
224 SmallVectorImpl<MachineInstr *> &
Uses)
const {
233void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
234 MachineBasicBlock *If, MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
235 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks,
236 SmallVectorImpl<Register> &CandidateRegs)
const {
238 SmallSet<Register, 8> KillsInElse;
240 for (
auto *Else : ElseBlocks) {
241 for (
auto &
MI :
Else->instrs()) {
242 if (
MI.isDebugInstr())
245 for (
auto &MO :
MI.operands()) {
246 if (!MO.isReg() || !MO.getReg() || MO.isDef())
251 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
260 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
261 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
265 if (!
VI.isLiveIn(*Endif, MOReg, *MRI)) {
266 KillsInElse.
insert(MOReg);
269 <<
" as Live in Endif\n");
279 for (
auto &
MI :
Endif->phis()) {
280 for (
unsigned Idx = 1; Idx <
MI.getNumOperands(); Idx += 2) {
281 auto &MO =
MI.getOperand(Idx);
282 auto *Pred =
MI.getOperand(Idx + 1).getMBB();
285 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
287 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
296 if (
VI.isLiveIn(*Endif,
Reg, *MRI)) {
298 <<
" as Live in Endif\n");
305 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
306 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
318 if (UseMBB ==
Flow || UseMBB == Endif) {
325 if ((UseMBB ==
Flow && IncomingMBB != If) ||
326 (UseMBB == Endif && IncomingMBB ==
Flow))
333 for (
auto Reg : KillsInElse) {
334 if (!IsLiveThroughThen(
Reg))
341void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
342 MachineBasicBlock *LoopHeader, MachineBasicBlock *LoopEnd,
343 SmallSetVector<Register, 16> &CandidateRegs,
344 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
345 SmallVectorImpl<MachineInstr *> &Instructions)
const {
348 auto *
MBB = LoopHeader;
351 for (
auto &
MI : *
MBB) {
352 if (
MI.isDebugInstr())
368 for (
auto *
I : Instructions) {
371 for (
auto &MO :
MI.all_uses()) {
377 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
387 LiveVariables::VarInfo &OldVarInfo = LV->
getVarInfo(MOReg);
391 OldVarInfo.
isLiveIn(*Succ, MOReg, *MRI)) {
399 CandidateRegs.
insert(MOReg);
411void SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion(
413 SetVector<MachineBasicBlock *> Blocks;
418 while (!WorkList.empty()) {
419 auto *
MBB = WorkList.pop_back_val();
422 WorkList.push_back(Succ);
427 for (MachineBasicBlock *
MBB : Blocks) {
434 SmallPtrSet<MachineBasicBlock *, 4> PHIIncoming;
446 for (MachineBasicBlock *
MBB : Blocks) {
451 if (
Uses.size() == 1) {
455 }
else if (
Uses.size() > 1) {
459 for (MachineInstr &
MI : *
MBB) {
472 for (
auto *
MI : OldVarInfo.
Kills) {
473 if (Blocks.contains(
MI->getParent()))
478void SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion(
480 MachineBasicBlock *Endif,
481 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
482 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
486 for (
auto *
MBB : ElseBlocks) {
498 if (!ElseBlocks.contains(MI->getParent()))
500 NewVarInfo.Kills.push_back(MI);
505void SIOptimizeVGPRLiveRange::optimizeLiveRange(
507 MachineBasicBlock *Endif,
508 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
516 TII->get(TargetOpcode::PHI), NewReg);
517 for (
auto *Pred :
Flow->predecessors()) {
519 PHI.addReg(
Reg).addMBB(Pred);
521 PHI.addReg(UndefReg, RegState::Undef).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(
560 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
561 SmallVectorImpl<MachineInstr *> &Instructions)
const {
571 auto *
UseMI =
O.getParent();
578 MachineInstrBuilder
PHI =
580 TII->get(TargetOpcode::PHI), NewReg);
583 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
585 PHI.addReg(
Reg).addMBB(Pred);
588 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
592 MachineInstr *
Kill =
nullptr;
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");
603 MachineBasicBlock *KillBlock =
Kill->getParent();
604 bool PostKillBlock =
false;
605 for (
auto *
Block : Blocks) {
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;
681 for (
auto &
MI :
MBB.terminators()) {
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,
723 Blocks, Instructions);
724 MadeChange |= !CandidateRegs.
empty();
726 for (
auto Reg : CandidateRegs)
727 optimizeWaterfallLiveRange(
Reg, LoopHeader, Blocks, Instructions);
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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)
Remove Loads Into Fake Uses
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.
LLVM_ABI void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *DefBlock, MachineBasicBlock *BB)
LLVM_ABI void HandleVirtRegUse(Register reg, MachineBasicBlock *MBB, MachineInstr &MI)
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
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...
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...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
const MachineBasicBlock * getParent() const
bool isDebugInstr() const
const MachineOperand & getOperand(unsigned i) const
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineBasicBlock * getMBB() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
static use_nodbg_iterator use_nodbg_end()
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
iterator_range< use_iterator > use_operands(Register Reg) const
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)
size_type size() const
Determine the number of elements in the SetVector.
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
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
A SetVector that performs no allocations if smaller than a certain size.
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
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.
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.
@ Kill
The last use of a register.
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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createSIOptimizeVGPRLiveRangeLegacyPass()
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
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.
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?