87#define DEBUG_TYPE "si-opt-vgpr-liverange"
91class SIOptimizeVGPRLiveRange {
127 void collectWaterfallCandidateRegisters(
138 void optimizeWaterfallLiveRange(
153 return "SI Optimize VGPR LiveRange";
182 if (
BR.getOpcode() == AMDGPU::SI_ELSE)
183 return BR.getOperand(2).getMBB();
188bool SIOptimizeVGPRLiveRange::isLiveThrough(
194bool SIOptimizeVGPRLiveRange::isLiveIntoMBB(
200void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
201 MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
202 SmallSetVector<MachineBasicBlock *, 16> &Blocks)
const {
213 if (Cur < Blocks.
size())
220 dbgs() <<
"Found Else blocks: ";
221 for (
auto *
MBB : Blocks)
229void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
230 MachineBasicBlock *If, MachineBasicBlock *
Flow, MachineBasicBlock *Endif,
231 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks,
232 SmallVectorImpl<Register> &CandidateRegs)
const {
234 SmallSet<Register, 8> KillsInElse;
236 for (
auto *Else : ElseBlocks) {
237 for (
auto &
MI :
Else->instrs()) {
238 if (
MI.isDebugInstr())
241 for (
auto &MO :
MI.operands()) {
242 if (!MO.isReg() || !MO.getReg() || MO.isDef())
247 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
251 const MachineBasicBlock *DefMBB = MRI->
getDefBlock(MOReg);
256 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If)) {
259 if (!isLiveIntoMBB(MOReg, Endif)) {
260 KillsInElse.
insert(MOReg);
263 <<
" as Live in Endif\n");
273 for (
auto &
MI :
Endif->phis()) {
274 for (
unsigned Idx = 1; Idx <
MI.getNumOperands(); Idx += 2) {
275 auto &MO =
MI.getOperand(Idx);
276 auto *Pred =
MI.getOperand(Idx + 1).getMBB();
279 assert(ElseBlocks.contains(Pred) &&
"Should be from Else region\n");
281 if (!MO.isReg() || !MO.getReg() || MO.isUndef())
288 if (isLiveIntoMBB(
Reg, Endif)) {
290 <<
" as Live in Endif\n");
298 Loops->getLoopFor(DefMBB) ==
Loops->getLoopFor(If))
310 if (UseMBB ==
Flow || UseMBB == Endif) {
317 if ((UseMBB ==
Flow && IncomingMBB != If) ||
318 (UseMBB == Endif && IncomingMBB ==
Flow))
325 for (
auto Reg : KillsInElse) {
326 if (!IsLiveThroughThen(
Reg))
333void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
334 MachineBasicBlock *LoopHeader, MachineBasicBlock *LoopEnd,
335 SmallSetVector<Register, 16> &CandidateRegs,
336 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
337 SmallVectorImpl<MachineInstr *> &Instructions)
const {
340 auto *
MBB = LoopHeader;
343 for (
auto &
MI : *
MBB) {
344 if (
MI.isDebugInstr())
360 for (
auto *
I : Instructions) {
363 for (
auto &MO :
MI.all_uses()) {
369 if (MOReg.
isPhysical() || !
TRI->isVectorRegister(*MRI, MOReg))
373 MachineBasicBlock *DefMBB = MRI->
getDefBlock(MOReg);
381 if (!Blocks.
contains(Succ) && isLiveIntoMBB(MOReg, Succ)) {
389 CandidateRegs.
insert(MOReg);
400void SIOptimizeVGPRLiveRange::optimizeLiveRange(
402 MachineBasicBlock *Endif,
403 SmallSetVector<MachineBasicBlock *, 16> &ElseBlocks)
const {
411 TII->get(TargetOpcode::PHI), NewReg);
412 for (
auto *Pred :
Flow->predecessors()) {
414 PHI.addReg(
Reg).addMBB(Pred);
416 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
422 auto *
UseMI =
O.getParent();
425 if (UseBlock == Endif) {
458void SIOptimizeVGPRLiveRange::optimizeWaterfallLiveRange(
460 SmallSetVector<MachineBasicBlock *, 2> &Blocks,
461 SmallVectorImpl<MachineInstr *> &Instructions)
const {
471 auto *
UseMI =
O.getParent();
478 MachineInstrBuilder
PHI =
480 TII->get(TargetOpcode::PHI), NewReg);
483 PHI.addReg(UndefReg, RegState::Undef).addMBB(Pred);
485 PHI.addReg(
Reg).addMBB(Pred);
495char SIOptimizeVGPRLiveRangeLegacy::ID = 0;
498 "SI Optimize VGPR LiveRange",
false,
false)
508 return new SIOptimizeVGPRLiveRangeLegacy();
511bool SIOptimizeVGPRLiveRangeLegacy::runOnMachineFunction(
MachineFunction &MF) {
515 LiveIntervals *LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
517 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
519 return SIOptimizeVGPRLiveRange(LIS, MDT,
Loops).run(MF);
530 bool Changed = SIOptimizeVGPRLiveRange(LIS, MDT,
Loops).run(MF);
543 TII = ST.getInstrInfo();
544 TRI = &
TII->getRegisterInfo();
547 bool MadeChange =
false;
552 for (
auto &
MI :
MBB.terminators()) {
554 if (
MI.getOpcode() == AMDGPU::SI_IF) {
556 auto *Endif = getElseTarget(IfTarget);
573 collectElseRegionBlocks(IfTarget, Endif, ElseBlocks);
576 collectCandidateRegisters(&
MBB, IfTarget, Endif, ElseBlocks,
578 MadeChange |= !CandidateRegs.
empty();
580 for (
auto Reg : CandidateRegs)
581 optimizeLiveRange(Reg, &
MBB, IfTarget, Endif, ElseBlocks);
582 }
else if (
MI.getOpcode() == AMDGPU::SI_WATERFALL_LOOP) {
583 auto *LoopHeader =
MI.getOperand(0).getMBB();
584 auto *LoopEnd = &
MBB;
593 collectWaterfallCandidateRegisters(LoopHeader, LoopEnd, CandidateRegs,
594 Blocks, Instructions);
595 MadeChange |= !CandidateRegs.
empty();
597 for (
auto Reg : CandidateRegs)
598 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)
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.
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)
An RAII based helper class to modify MachineFunctionProperties when running pass.
unsigned pred_size() const
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_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.
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.
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.
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
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createSIOptimizeVGPRLiveRangeLegacyPass()
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.