66#define DEBUG_TYPE "si-lower-control-flow"
74class SILowerControlFlow {
91 bool EnableOptimizeEndCf =
false;
126 while (
I != End && !
I->isUnconditionalBranch())
132 void optimizeEndCf();
135 SILowerControlFlow(
const GCNSubtarget *ST, LiveIntervals *LIS,
136 LiveVariables *LV, MachineDominatorTree *MDT,
137 MachinePostDominatorTree *PDT)
138 : LIS(LIS), LV(LV), MDT(MDT), PDT(PDT),
139 LMC(AMDGPU::LaneMaskConstants::
get(*
ST)) {}
147 SILowerControlFlowLegacy() : MachineFunctionPass(ID) {}
151 StringRef getPassName()
const override {
152 return "SI Lower control flow pseudo instructions";
155 void getAnalysisUsage(AnalysisUsage &AU)
const override {
164 AU.
addPreserved<MachineBlockFrequencyInfoWrapperPass>();
171char SILowerControlFlowLegacy::ID = 0;
190 while (!Worklist.
empty()) {
205 Register SaveExecReg =
MI.getOperand(0).getReg();
216void SILowerControlFlow::emitIf(MachineInstr &
MI) {
220 Register SaveExecReg =
MI.getOperand(0).getReg();
221 MachineOperand&
Cond =
MI.getOperand(1);
222 assert(
Cond.getSubReg() == AMDGPU::NoSubRegister);
224 MachineOperand &ImpDefSCC =
MI.getOperand(4);
241 Register CopyReg = SimpleIf ? SaveExecReg
243 MachineInstr *CopyExec =
BuildMI(
MBB,
I,
DL,
TII->get(AMDGPU::COPY), CopyReg)
246 LoweredIf.
insert(CopyReg);
255 setImpSCCDefDead(*
And,
true);
257 MachineInstr *
Xor =
nullptr;
262 setImpSCCDefDead(*
Xor, ImpDefSCC.
isDead());
267 MachineInstr *SetExec =
269 .
addReg(Tmp, RegState::Kill);
275 I = skipToUncondBrOrEnd(
MBB,
I);
279 MachineInstr *NewBr =
BuildMI(
MBB,
I,
DL,
TII->get(AMDGPU::S_CBRANCH_EXECZ))
280 .
add(
MI.getOperand(2));
283 MI.eraseFromParent();
298 MI.eraseFromParent();
303 RecomputeRegs.
insert(SaveExecReg);
309void SILowerControlFlow::emitElse(MachineInstr &
MI) {
321 MachineInstr *OrSaveExec =
323 .
add(
MI.getOperand(1));
327 MachineBasicBlock *DestBB =
MI.getOperand(2).getMBB();
344 ElsePt = skipToUncondBrOrEnd(
MBB, ElsePt);
351 MI.eraseFromParent();
356 MI.eraseFromParent();
364 RecomputeRegs.
insert(SrcReg);
365 RecomputeRegs.
insert(DstReg);
369void SILowerControlFlow::emitIfBreak(MachineInstr &
MI) {
372 auto Dst =
MI.getOperand(0).getReg();
378 bool SkipAnding =
false;
379 if (
MI.getOperand(1).isReg()) {
381 SkipAnding =
Def->getParent() ==
MI.getParent() &&
388 MachineInstr *
And =
nullptr, *
Or =
nullptr;
394 .
add(
MI.getOperand(1));
399 .
add(
MI.getOperand(2));
402 .
add(
MI.getOperand(1))
403 .
add(
MI.getOperand(2));
414 RecomputeRegs.
insert(
And->getOperand(2).getReg());
420 MI.eraseFromParent();
423void SILowerControlFlow::emitLoop(MachineInstr &
MI) {
427 MachineInstr *AndN2 =
430 .
add(
MI.getOperand(0));
437 .
add(
MI.getOperand(1));
440 RecomputeRegs.
insert(
MI.getOperand(0).getReg());
445 MI.eraseFromParent();
449SILowerControlFlow::skipIgnoreExecInstsTrivialSucc(
452 SmallPtrSet<const MachineBasicBlock *, 4> Visited;
453 MachineBasicBlock *
B = &
MBB;
459 for ( ; It !=
E; ++It) {
460 if (
TII->mayReadEXEC(*MRI, *It))
467 if (
B->succ_size() != 1)
471 MachineBasicBlock *Succ = *
B->succ_begin();
478MachineBasicBlock *SILowerControlFlow::emitEndCf(MachineInstr &
MI) {
487 bool NeedBlockSplit =
false;
491 if (
I->modifiesRegister(DataReg,
TRI)) {
492 NeedBlockSplit =
true;
497 unsigned Opcode = LMC.
OrOpc;
498 MachineBasicBlock *SplitBB = &
MBB;
499 if (NeedBlockSplit) {
501 if (SplitBB != &
MBB && (MDT || PDT)) {
504 for (MachineBasicBlock *Succ : SplitBB->
successors()) {
505 DTUpdates.
push_back({DomTreeT::Insert, SplitBB, Succ});
520 .
add(
MI.getOperand(0));
524 if (SplitBB != &
MBB) {
529 DenseSet<Register> DefInOrigBlock;
531 for (MachineBasicBlock *BlockPiece : {&
MBB, SplitBB}) {
532 for (MachineInstr &
X : *BlockPiece) {
533 for (MachineOperand &
Op :
X.all_defs()) {
534 if (
Op.getReg().isVirtual())
547 for (MachineInstr *
Kill :
VI.Kills) {
556 LoweredEndCf.
insert(NewMI);
561 MI.eraseFromParent();
570void SILowerControlFlow::findMaskOperands(
571 MachineInstr &
MI,
unsigned OpNo,
572 SmallVectorImpl<MachineOperand *> &Src)
const {
573 MachineOperand &
Op =
MI.getOperand(OpNo);
574 if (!
Op.isReg() || !
Op.getReg().isVirtual()) {
580 if (!Def ||
Def->getParent() !=
MI.getParent() ||
581 !(
Def->isFullCopy() || (
Def->getOpcode() ==
MI.getOpcode())))
587 for (
auto I =
Def->getIterator();
I !=
MI.getIterator(); ++
I)
588 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI) &&
589 !(
I->isCopy() &&
I->getOperand(0).getReg() != LMC.
ExecReg))
592 for (MachineOperand &SrcOp :
Def->explicit_operands())
593 if (SrcOp.isReg() && SrcOp.isUse() &&
594 (SrcOp.getReg().isVirtual() || SrcOp.getReg() == LMC.
ExecReg))
595 Src.push_back(&SrcOp);
602void SILowerControlFlow::combineMasks(MachineInstr &
MI) {
603 assert(
MI.getNumExplicitOperands() == 3);
605 findMaskOperands(
MI, 1, Src1);
606 findMaskOperands(
MI, 2, Src2);
610 unsigned OpToReplace;
611 MachineOperand *Leaf, *NestedLHS, *NestedRHS;
612 if (Src1.
size() == 2 && Src2.
size() == 1) {
617 }
else if (Src1.
size() == 1 && Src2.
size() == 2) {
627 MachineOperand *KeepOp;
637 MI.removeOperand(OpToReplace);
638 MI.addOperand(*KeepOp);
643void SILowerControlFlow::optimizeEndCf() {
646 if (!EnableOptimizeEndCf)
649 for (MachineInstr *
MI :
reverse(LoweredEndCf)) {
652 skipIgnoreExecInstsTrivialSucc(
MBB, std::next(
MI->getIterator()));
658 =
TII->getNamedOperand(*
Next, AMDGPU::OpName::src1)->getReg();
662 if (Def && LoweredIf.
count(SavedExec)) {
668 Reg =
TII->getNamedOperand(*
MI, AMDGPU::OpName::src1)->getReg();
669 MI->eraseFromParent();
672 removeMBBifRedundant(
MBB);
677MachineBasicBlock *SILowerControlFlow::process(MachineInstr &
MI) {
680 MachineInstr *Prev = (
I !=
MBB.
begin()) ? &*(std::prev(
I)) : nullptr;
682 MachineBasicBlock *SplitBB = &
MBB;
684 switch (
MI.getOpcode()) {
689 case AMDGPU::SI_ELSE:
693 case AMDGPU::SI_IF_BREAK:
697 case AMDGPU::SI_LOOP:
701 case AMDGPU::SI_WATERFALL_LOOP:
702 MI.setDesc(
TII->get(AMDGPU::S_CBRANCH_EXECNZ));
705 case AMDGPU::SI_END_CF:
706 SplitBB = emitEndCf(
MI);
710 assert(
false &&
"Attempt to process unsupported instruction");
717 MachineInstr &MaskMI = *
I;
719 case AMDGPU::S_AND_B64:
720 case AMDGPU::S_OR_B64:
721 case AMDGPU::S_AND_B32:
722 case AMDGPU::S_OR_B32:
724 combineMasks(MaskMI);
735bool SILowerControlFlow::removeMBBifRedundant(MachineBasicBlock &
MBB) {
737 if (!
I.isDebugInstr() && !
I.isUnconditionalBranch())
744 MachineBasicBlock *FallThrough =
nullptr;
751 if (
P->getFallThrough(
false) == &
MBB)
754 DTUpdates.
push_back({DomTreeT::Insert,
P, Succ});
777 MachineInstr *BranchMI =
BuildMI(*FallThrough, FallThrough->
end(),
789 TII =
ST.getInstrInfo();
795 BoolRC =
TRI->getBoolRC();
798 const bool CanDemote =
800 for (
auto &
MBB : MF) {
801 bool IsKillBlock =
false;
803 if (
TII->isKillTerminator(
Term.getOpcode())) {
809 if (CanDemote && !IsKillBlock) {
810 for (
auto &
MI :
MBB) {
811 if (
MI.getOpcode() == AMDGPU::SI_DEMOTE_I1) {
822 BI != MF.end(); BI = NextBB) {
823 NextBB = std::next(BI);
824 MachineBasicBlock *
MBB = &*BI;
830 MachineInstr &
MI = *
I;
831 MachineBasicBlock *SplitMBB =
MBB;
833 switch (
MI.getOpcode()) {
835 case AMDGPU::SI_ELSE:
836 case AMDGPU::SI_IF_BREAK:
837 case AMDGPU::SI_WATERFALL_LOOP:
838 case AMDGPU::SI_LOOP:
839 case AMDGPU::SI_END_CF:
840 SplitMBB = process(
MI);
845 if (SplitMBB !=
MBB) {
864 RecomputeRegs.clear();
865 LoweredEndCf.
clear();
872bool SILowerControlFlowLegacy::runOnMachineFunction(
MachineFunction &MF) {
875 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
876 LiveIntervals *LIS = LISWrapper ? &LISWrapper->getLIS() :
nullptr;
878 auto *LVWrapper = getAnalysisIfAvailable<LiveVariablesWrapperPass>();
879 LiveVariables *LV = LVWrapper ? &LVWrapper->getLV() :
nullptr;
880 auto *MDTWrapper = getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>();
881 MachineDominatorTree *MDT = MDTWrapper ? &MDTWrapper->getDomTree() :
nullptr;
883 getAnalysisIfAvailable<MachinePostDominatorTreeWrapperPass>();
884 MachinePostDominatorTree *PDT =
885 PDTWrapper ? &PDTWrapper->getPostDomTree() :
nullptr;
886 return SILowerControlFlow(ST, LIS, LV, MDT, PDT).run(MF);
900 bool Changed = SILowerControlFlow(ST, LIS, LV, MDT, PDT).run(MF);
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< bool > RemoveRedundantEndcf("amdgpu-remove-redundant-endcf", cl::init(true), cl::ReallyHidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isSimpleIf(const MachineInstr &MI, const MachineRegisterInfo *MRI)
const unsigned XorTermOpc
const unsigned MovTermOpc
const unsigned OrSaveExecOpc
const unsigned AndN2TermOpc
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
AnalysisUsage & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Implements a dense probed hash-table based set.
void applyUpdates(ArrayRef< UpdateType > Updates)
Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...
void eraseNode(NodeT *BB)
eraseNode - Removes a node from the dominator tree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
const HexagonRegisterInfo & getRegisterInfo() const
void removeAllRegUnitsForPhysReg(MCRegister Reg)
Remove associated live ranges for the register units associated with Reg.
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
LLVM_ABI void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
void removeInterval(Register Reg)
Interval removal.
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
SlotIndex ReplaceMachineInstrInMaps(MachineInstr &MI, MachineInstr &NewMI)
LLVM_ABI void replaceKillInstruction(Register Reg, MachineInstr &OldMI, MachineInstr &NewMI)
replaceKillInstruction - Update register kill info by replacing a kill instruction with a new one.
LLVM_ABI void recomputeForSingleDefVirtReg(Register Reg)
Recompute liveness from scratch for a virtual register Reg that is known to have a single def that do...
LLVM_ABI VarInfo & getVarInfo(Register Reg)
getVarInfo - Return the VarInfo structure for the specified VIRTUAL register.
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 void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
pred_iterator pred_begin()
LLVM_ABI void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New)
Given a machine basic block that branched to 'Old', change the code and CFG so that it branches to 'N...
LLVM_ABI bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< iterator > terminators()
LLVM_ABI DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
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.
BasicBlockListType::iterator iterator
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
void setIsDead(bool Val=true)
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
MachinePostDominatorTree - an analysis pass wrapper for DominatorTree used to compute the post-domina...
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static use_instr_nodbg_iterator use_instr_nodbg_end()
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
A vector that has set insertion semantics.
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
void clear()
Completely clear the SetVector.
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
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
self_iterator getIterator()
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
NodeAddr< DefNode * > Def
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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
DominatorTreeBase< T, false > DomTreeBase
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...
char & SILowerControlFlowLegacyID
@ Or
Bitwise or logical OR of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
MCRegisterClass TargetRegisterClass
std::vector< MachineInstr * > Kills
Kills - List of MachineInstruction's which are the last use of this virtual register (kill it) in the...