88#define DEBUG_TYPE "si-opt-vgpr-liverange"
92class SIOptimizeVGPRLiveRange {
129 void collectWaterfallCandidateRegisters(
141 void updateLiveRangeInElseRegion(
151 void optimizeWaterfallLiveRange(
166 return "SI Optimize VGPR LiveRange";
196 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
197 return BR.getOperand(2).getMBB();
202bool SIOptimizeVGPRLiveRange::isLiveThrough(
211bool SIOptimizeVGPRLiveRange::isLiveIntoMBB(
220void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
221 MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
222 SmallSetVector<MachineBasicBlock *, 16> &Blocks)
const {
233 if (Cur < Blocks.
size())
240 dbgs() <<
"Found Else blocks: ";
241 for (
auto *
MBB : Blocks)
248void SIOptimizeVGPRLiveRange::findNonPHIUsesInBlock(
250 SmallVectorImpl<MachineInstr *> &
Uses)
const {
260void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
261 MachineBasicBlock *If, MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
262 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks,
263 SmallVectorImpl<Register> &CandidateRegs)
const {
265 SmallSet<Register, 8> KillsInElse;
267 for (
auto *Else : ElseBlocks) {
268 for (
auto &
MI :
Else->instrs()) {
269 if (
MI.isDebugInstr())
272 for (
auto &MO :
MI.operands()) {
273 if (!MO.isReg() || !MO.getReg() || MO.isDef())
278 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
282 const MachineBasicBlock *DefMBB = MRI->
getDefBlock(MOReg);
287 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
290 if (!isLiveIntoMBB(MOReg, Endif)) {
291 KillsInElse.
insert(MOReg);
294 <<
" as Live in Endif\n");
304 for (
auto &
MI :
Endif->phis()) {
305 for (
unsigned Idx = 1; Idx <
MI.getNumOperands(); Idx += 2) {
306 auto &MO =
MI.getOperand(Idx);
307 auto *Pred =
MI.getOperand(Idx + 1).getMBB();
310 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
312 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
319 if (isLiveIntoMBB(
Reg, Endif)) {
321 <<
" as Live in Endif\n");
329 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
341 if (UseMBB ==
Flow || UseMBB == Endif) {
348 if ((UseMBB ==
Flow && IncomingMBB != If) ||
349 (UseMBB == Endif && IncomingMBB ==
Flow))
356 for (
auto Reg : KillsInElse) {
357 if (!IsLiveThroughThen(
Reg))
364void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
365 MachineBasicBlock *LoopHeader, MachineBasicBlock *LoopEnd,
366 SmallSetVector<Register, 16> &CandidateRegs,
367 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
368 SmallVectorImpl<MachineInstr *> &Instructions)
const {
371 auto *
MBB = LoopHeader;
374 for (
auto &
MI : *
MBB) {
375 if (
MI.isDebugInstr())
391 for (
auto *
I : Instructions) {
394 for (
auto &MO :
MI.all_uses()) {
400 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
404 MachineBasicBlock *DefMBB = MRI->
getDefBlock(MOReg);
412 if (!Blocks.
contains(Succ) && isLiveIntoMBB(MOReg, Succ)) {
420 CandidateRegs.
insert(MOReg);
432void SIOptimizeVGPRLiveRange::updateLiveRangeInThenRegion(
434 SetVector<MachineBasicBlock *> Blocks;
439 while (!WorkList.empty()) {
440 auto *
MBB = WorkList.pop_back_val();
443 WorkList.push_back(Succ);
448 for (MachineBasicBlock *
MBB : Blocks) {
455 SmallPtrSet<MachineBasicBlock *, 4> PHIIncoming;
467 for (MachineBasicBlock *
MBB : Blocks) {
472 if (
Uses.size() == 1) {
476 }
else if (
Uses.size() > 1) {
480 for (MachineInstr &
MI : *
MBB) {
492 for (
auto *
MI : OldVarInfo.
Kills) {
493 if (Blocks.contains(
MI->getParent()))
498void SIOptimizeVGPRLiveRange::updateLiveRangeInElseRegion(
500 MachineBasicBlock *Endif,
501 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
502 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
506 for (
auto *
MBB : ElseBlocks) {
518 if (!ElseBlocks.contains(MI->getParent()))
520 NewVarInfo.Kills.push_back(MI);
525void SIOptimizeVGPRLiveRange::optimizeLiveRange(
527 MachineBasicBlock *Endif,
528 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
536 TII->get(TargetOpcode::PHI), NewReg);
537 for (
auto *Pred :
Flow->predecessors()) {
539 PHI.addReg(
Reg).addMBB(Pred);
541 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
547 auto *
UseMI =
O.getParent();
550 if (UseBlock == Endif) {
589 updateLiveRangeInElseRegion(
Reg, NewReg,
Flow, Endif, ElseBlocks);
590 updateLiveRangeInThenRegion(
Reg, If,
Flow);
594void SIOptimizeVGPRLiveRange::optimizeWaterfallLiveRange(
596 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
597 SmallVectorImpl<MachineInstr *> &Instructions)
const {
607 auto *
UseMI =
O.getParent();
614 MachineInstrBuilder
PHI =
616 TII->get(TargetOpcode::PHI), NewReg);
619 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
621 PHI.addReg(
Reg).addMBB(Pred);
633 LiveVariables::VarInfo &NewVarInfo = LV->
getVarInfo(NewReg);
637 MachineInstr *
Kill =
nullptr;
639 if (
MI->readsRegister(NewReg,
TRI)) {
640 MI->addRegisterKilled(NewReg,
TRI);
641 NewVarInfo.
Kills.push_back(
MI);
646 assert(
Kill &&
"Failed to find last usage of register in loop");
648 MachineBasicBlock *KillBlock =
Kill->getParent();
649 bool PostKillBlock =
false;
650 for (
auto *
Block : Blocks) {
651 auto BBNum =
Block->getNumber();
659 PostKillBlock |= (
Block == KillBlock);
662 }
else if (
Block != LoopHeader) {
669char SIOptimizeVGPRLiveRangeLegacy::ID = 0;
672 "SI Optimize VGPR LiveRange",
false,
false)
682 return new SIOptimizeVGPRLiveRangeLegacy();
685bool SIOptimizeVGPRLiveRangeLegacy::runOnMachineFunction(
MachineFunction &MF) {
689 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
690 LiveIntervals *LIS = LISWrapper ? &LISWrapper->getLIS() :
nullptr;
691 LiveVariables *LV = &getAnalysis<LiveVariablesWrapperPass>().getLV();
693 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
695 return SIOptimizeVGPRLiveRange(LIS, LV, MDT,
Loops).run(MF);
709 bool Changed = SIOptimizeVGPRLiveRange(LIS, LV, MDT,
Loops).run(MF);
722 TII = ST.getInstrInfo();
723 TRI = &
TII->getRegisterInfo();
726 bool MadeChange =
false;
731 for (
auto &
MI :
MBB.terminators()) {
733 if (
MI.getOpcode() == AMDGPU::SI_IF) {
735 auto *Endif = getElseTarget(IfTarget);
752 collectElseRegionBlocks(IfTarget, Endif, ElseBlocks);
755 collectCandidateRegisters(&
MBB, IfTarget, Endif, ElseBlocks,
757 MadeChange |= !CandidateRegs.
empty();
759 for (
auto Reg : CandidateRegs)
760 optimizeLiveRange(Reg, &
MBB, IfTarget, Endif, ElseBlocks);
761 }
else if (
MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP) {
762 auto *LoopHeader =
MI.getOperand(0).getMBB();
763 auto *LoopEnd = &
MBB;
772 collectWaterfallCandidateRegisters(LoopHeader, LoopEnd, CandidateRegs,
773 Blocks, Instructions);
774 MadeChange |= !CandidateRegs.
empty();
776 for (
auto Reg : CandidateRegs)
777 optimizeWaterfallLiveRange(
Reg, LoopHeader, Blocks, Instructions);
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
static bool isLiveThrough(const LiveQueryResult Q)
Remove Loads Into Fake Uses
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
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 & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this 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.
FunctionPass class - This class is used to implement most global optimizations.
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
LiveInterval & getInterval(Register Reg)
void removeInterval(Register Reg)
Interval removal.
bool isLiveOutOfMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const
bool isLiveInToMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
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 void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
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.
@ 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?