88#define DEBUG_TYPE "si-opt-vgpr-liverange"
92class SIOptimizeVGPRLiveRange {
119 void collectWaterfallCandidateRegisters(
131 void updateLiveRangeInElseRegion(
141 void optimizeWaterfallLiveRange(
156 return "SI Optimize VGPR LiveRange";
186 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
187 return BR.getOperand(2).getMBB();
192void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
193 MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
194 SmallSetVector<MachineBasicBlock *, 16> &Blocks)
const {
205 if (Cur < Blocks.
size())
212 dbgs() <<
"Found Else blocks: ";
213 for (
auto *
MBB : Blocks)
220void SIOptimizeVGPRLiveRange::findNonPHIUsesInBlock(
222 SmallVectorImpl<MachineInstr *> &
Uses)
const {
223 for (
auto &
UseMI :
MRI->use_nodbg_instructions(
Reg)) {
231void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
232 MachineBasicBlock *If, MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
233 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks,
234 SmallVectorImpl<Register> &CandidateRegs)
const {
236 SmallSet<Register, 8> KillsInElse;
238 for (
auto *Else : ElseBlocks) {
239 for (
auto &
MI :
Else->instrs()) {
240 if (
MI.isDebugInstr())
243 for (
auto &MO :
MI.operands()) {
244 if (!MO.isReg() || !MO.getReg() || MO.isDef())
254 const MachineBasicBlock *DefMBB =
MRI->getVRegDef(MOReg)->getParent();
258 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
259 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
263 if (!
VI.isLiveIn(*Endif, MOReg, *
MRI)) {
264 KillsInElse.
insert(MOReg);
267 <<
" as Live in Endif\n");
277 for (
auto &
MI :
Endif->phis()) {
278 for (
unsigned Idx = 1; Idx <
MI.getNumOperands(); Idx += 2) {
279 auto &MO =
MI.getOperand(Idx);
280 auto *Pred =
MI.getOperand(Idx + 1).getMBB();
283 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
285 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
294 if (
VI.isLiveIn(*Endif,
Reg, *
MRI)) {
296 <<
" as Live in Endif\n");
302 const MachineBasicBlock *DefMBB =
MRI->getVRegDef(
Reg)->getParent();
303 if ((
VI.AliveBlocks.test(
If->getNumber()) || DefMBB == If) &&
304 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
310 for (
auto I =
MRI->use_nodbg_begin(
Reg),
E =
MRI->use_nodbg_end();
I !=
E;
316 if (UseMBB ==
Flow || UseMBB == Endif) {
323 if ((UseMBB ==
Flow && IncomingMBB != If) ||
324 (UseMBB == Endif && IncomingMBB ==
Flow))
331 for (
auto Reg : KillsInElse) {
332 if (!IsLiveThroughThen(
Reg))
339void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
340 MachineBasicBlock *LoopHeader, MachineBasicBlock *LoopEnd,
341 SmallSetVector<Register, 16> &CandidateRegs,
342 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
343 SmallVectorImpl<MachineInstr *> &Instructions)
const {
346 auto *
MBB = LoopHeader;
349 for (
auto &
MI : *
MBB) {
350 if (
MI.isDebugInstr())
366 for (
auto *
I : Instructions) {
369 for (
auto &MO :
MI.all_uses()) {
379 MachineBasicBlock *DefMBB =
MRI->getVRegDef(MOReg)->getParent();
385 LiveVariables::VarInfo &OldVarInfo = LV->
getVarInfo(MOReg);
397 CandidateRegs.
insert(MOReg);
409void SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion(
411 SetVector<MachineBasicBlock *> Blocks;
416 while (!WorkList.empty()) {
417 auto *
MBB = WorkList.pop_back_val();
420 WorkList.push_back(Succ);
425 for (MachineBasicBlock *
MBB : Blocks) {
432 SmallPtrSet<MachineBasicBlock *, 4> PHIIncoming;
435 for (
auto I =
MRI->use_nodbg_begin(
Reg),
E =
MRI->use_nodbg_end();
I !=
E;
444 for (MachineBasicBlock *
MBB : Blocks) {
449 if (
Uses.size() == 1) {
453 }
else if (
Uses.size() > 1) {
457 for (MachineInstr &
MI : *
MBB) {
470 for (
auto *
MI : OldVarInfo.
Kills) {
471 if (Blocks.contains(
MI->getParent()))
476void SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion(
478 MachineBasicBlock *Endif,
479 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
480 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
484 for (
auto *
MBB : ElseBlocks) {
495 auto I = OldVarInfo.
Kills.begin();
496 while (
I != OldVarInfo.
Kills.end()) {
497 if (ElseBlocks.contains((*I)->getParent())) {
498 NewVarInfo.
Kills.push_back(*
I);
506void SIOptimizeVGPRLiveRange::optimizeLiveRange(
508 MachineBasicBlock *Endif,
509 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
513 const auto *RC =
MRI->getRegClass(
Reg);
515 Register UndefReg =
MRI->createVirtualRegister(RC);
517 TII->get(TargetOpcode::PHI), NewReg);
518 for (
auto *Pred :
Flow->predecessors()) {
520 PHI.addReg(
Reg).addMBB(Pred);
522 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
528 auto *
UseMI =
O.getParent();
531 if (UseBlock == Endif) {
555 updateLiveRangeInElseRegion(
Reg, NewReg,
Flow, Endif, ElseBlocks);
556 updateLiveRangeInThenRegion(
Reg, If,
Flow);
559void SIOptimizeVGPRLiveRange::optimizeWaterfallLiveRange(
561 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
562 SmallVectorImpl<MachineInstr *> &Instructions)
const {
565 const auto *RC =
MRI->getRegClass(
Reg);
567 Register UndefReg =
MRI->createVirtualRegister(RC);
572 auto *
UseMI =
O.getParent();
579 MachineInstrBuilder
PHI =
581 TII->get(TargetOpcode::PHI), NewReg);
584 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
586 PHI.addReg(
Reg).addMBB(Pred);
589 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
593 MachineInstr *
Kill =
nullptr;
595 if (
MI->readsRegister(NewReg,
TRI)) {
596 MI->addRegisterKilled(NewReg,
TRI);
597 NewVarInfo.
Kills.push_back(
MI);
602 assert(
Kill &&
"Failed to find last usage of register in loop");
604 MachineBasicBlock *KillBlock =
Kill->getParent();
605 bool PostKillBlock =
false;
606 for (
auto *
Block : Blocks) {
607 auto BBNum =
Block->getNumber();
615 PostKillBlock |= (
Block == KillBlock);
618 }
else if (
Block != LoopHeader) {
624char SIOptimizeVGPRLiveRangeLegacy::ID = 0;
627 "SI Optimize VGPR LiveRange",
false,
false)
637 return new SIOptimizeVGPRLiveRangeLegacy();
640bool SIOptimizeVGPRLiveRangeLegacy::runOnMachineFunction(
MachineFunction &MF) {
644 LiveVariables *LV = &getAnalysis<LiveVariablesWrapperPass>().getLV();
646 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
648 return SIOptimizeVGPRLiveRange(LV, MDT,
Loops).run(MF);
659 bool Changed = SIOptimizeVGPRLiveRange(LV, MDT,
Loops).run(MF);
673 TII = ST.getInstrInfo();
674 TRI = &
TII->getRegisterInfo();
677 bool MadeChange =
false;
682 for (
auto &
MI :
MBB.terminators()) {
684 if (
MI.getOpcode() == AMDGPU::SI_IF) {
686 auto *Endif = getElseTarget(IfTarget);
703 collectElseRegionBlocks(IfTarget, Endif, ElseBlocks);
706 collectCandidateRegisters(&
MBB, IfTarget, Endif, ElseBlocks,
708 MadeChange |= !CandidateRegs.
empty();
710 for (
auto Reg : CandidateRegs)
711 optimizeLiveRange(Reg, &
MBB, IfTarget, Endif, ElseBlocks);
712 }
else if (
MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP) {
713 auto *LoopHeader =
MI.getOperand(0).getMBB();
714 auto *LoopEnd = &
MBB;
723 collectWaterfallCandidateRegisters(LoopHeader, LoopEnd, CandidateRegs,
724 Blocks, Instructions);
725 MadeChange |= !CandidateRegs.
empty();
727 for (
auto Reg : CandidateRegs)
728 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.
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,...
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
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.
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()
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?