29#define DEBUG_TYPE "si-i1-copies"
48 void markAsLaneMask(
Register DstReg)
const override;
49 void getCandidatesForLowering(
51 void collectIncomingValuesFromPhi(
62 bool lowerCopiesFromI1();
63 bool lowerCopiesToI1();
64 bool cleanConstrainRegs(
bool Changed);
66 return Reg.isVirtual() && MRI->getRegClass(
Reg) == &AMDGPU::VReg_1RegClass;
73 : PhiLoweringHelper(MF, DT, PDT) {}
75bool Vreg1LoweringHelper::cleanConstrainRegs(
bool Changed) {
79 ConstrainRegs.clear();
123 : PDT(PDT), TII(TII) {}
128 return ReachableMap.find(&
MBB)->second;
136 ReachableMap.clear();
137 Predecessors.clear();
141 ReachableMap.try_emplace(&DefBlock,
false);
145 if (
MBB == &DefBlock) {
146 ReachableMap[&DefBlock] =
true;
152 if (TII->hasDivergentBranch(
MBB) && PDT.dominates(&DefBlock,
MBB))
156 while (!Stack.empty()) {
158 if (ReachableMap.try_emplace(
MBB,
false).second)
165 ReachableMap.try_emplace(
MBB,
false);
168 for (
auto &[
MBB, IsSource] : ReachableMap) {
169 bool HaveReachablePred =
false;
171 if (ReachableMap.count(Pred)) {
172 HaveReachablePred =
true;
174 Stack.push_back(Pred);
177 if (!HaveReachablePred)
179 if (HaveReachablePred) {
182 Predecessors.push_back(UnreachablePred);
241 unsigned FoundLoopLevel = ~0u;
249 : DT(DT), PDT(PDT) {}
253 CommonDominators.clear();
256 VisitedPostDom =
nullptr;
257 FoundLoopLevel = ~0u;
273 while (PDNode->
getBlock() != PostDom) {
274 if (PDNode->
getBlock() == VisitedPostDom)
278 if (FoundLoopLevel == Level)
298 if (!inLoopLevel(*Dom, LoopLevel, Incomings)) {
305 if (!inLoopLevel(*Pred, LoopLevel, Incomings))
313 bool inLoopLevel(MachineBasicBlock &
MBB,
unsigned LoopLevel,
315 auto DomIt = Visited.
find(&
MBB);
316 if (DomIt != Visited.
end() && DomIt->second <= LoopLevel)
319 for (
auto &Incoming : Incomings)
320 if (Incoming.Block == &
MBB)
326 void advanceLevel() {
327 MachineBasicBlock *VisitedDom;
329 if (!VisitedPostDom) {
330 VisitedPostDom = DefBlock;
331 VisitedDom = DefBlock;
332 Stack.push_back(DefBlock);
334 VisitedPostDom = PDT.
getNode(VisitedPostDom)->getIDom()->getBlock();
335 VisitedDom = CommonDominators.
back();
337 for (
unsigned i = 0; i < NextLevel.
size();) {
338 if (PDT.
dominates(VisitedPostDom, NextLevel[i])) {
339 Stack.push_back(NextLevel[i]);
341 NextLevel[i] = NextLevel.
back();
349 unsigned Level = CommonDominators.
size();
350 while (!
Stack.empty()) {
351 MachineBasicBlock *
MBB =
Stack.pop_back_val();
359 if (Succ == DefBlock) {
360 if (
MBB == VisitedPostDom)
361 FoundLoopLevel = std::min(FoundLoopLevel, Level + 1);
363 FoundLoopLevel = std::min(FoundLoopLevel, Level);
368 if (
MBB == VisitedPostDom)
371 Stack.push_back(Succ);
395 BuildMI(*
MBB,
MBB->getFirstTerminator(), {},
TII->get(AMDGPU::IMPLICIT_DEF),
404 unsigned Size =
TRI.getRegSizeInBits(
Reg, MRI);
409bool Vreg1LoweringHelper::lowerCopiesFromI1() {
411 SmallVector<MachineInstr *, 4> DeadCopies;
413 for (MachineBasicBlock &
MBB : MF) {
414 for (MachineInstr &
MI :
MBB) {
415 if (
MI.getOpcode() != AMDGPU::COPY)
420 if (!isVreg1(SrcReg))
423 if (isLaneMaskReg(DstReg) || isVreg1(DstReg))
433 assert(!
MI.getOperand(0).getSubReg());
435 ConstrainRegs.insert(SrcReg);
445 for (MachineInstr *
MI : DeadCopies)
446 MI->eraseFromParent();
457 MRI = &
MF.getRegInfo();
459 TII =
ST->getInstrInfo();
473 return DT.getNode(LHS.Block)->getDFSNumIn() <
474 DT.getNode(RHS.Block)->getDFSNumIn();
489 unsigned FoundLoopLevel = LF.
findLoop(PostDomBound);
493 if (FoundLoopLevel) {
551 if (Vreg1Phis.
empty())
557 DT.updateDFSNumbers();
577 MI->eraseFromParent();
584bool Vreg1LoweringHelper::lowerCopiesToI1() {
593 if (
MI.getOpcode() != AMDGPU::IMPLICIT_DEF &&
594 MI.getOpcode() != AMDGPU::COPY)
598 if (!isVreg1(DstReg))
610 markAsLaneMask(DstReg);
611 initializeLaneMaskRegisterAttributes(DstReg);
613 if (
MI.getOpcode() == AMDGPU::IMPLICIT_DEF)
618 assert(!
MI.getOperand(1).getSubReg());
620 if (!SrcReg.
isVirtual() || (!isLaneMaskReg(SrcReg) && !isVreg1(SrcReg))) {
621 assert(
TII->getRegisterInfo().getRegSizeInBits(SrcReg, *MRI) == 32);
626 MI.getOperand(1).setReg(TmpReg);
630 MI.getOperand(1).setIsKill(
false);
635 std::vector<MachineBasicBlock *> DomBlocks = {&
MBB};
637 DomBlocks.push_back(
Use.getParent());
639 MachineBasicBlock *PostDomBound =
641 unsigned FoundLoopLevel = LF.findLoop(PostDomBound);
642 if (FoundLoopLevel) {
643 MachineIDFSSAUpdater SSAUpdater(DT, MF, DstReg);
646 LF.addLoopEntries(FoundLoopLevel, SSAUpdater, *MRI, LaneMaskRegAttrs);
649 buildMergeLaneMasks(
MBB,
MI,
DL, DstReg,
655 for (MachineInstr *
MI : DeadCopies)
656 MI->eraseFromParent();
666 MI =
MRI->getUniqueVRegDef(Reg);
667 if (
MI->getOpcode() == AMDGPU::IMPLICIT_DEF)
670 if (
MI->getOpcode() != AMDGPU::COPY)
673 Reg =
MI->getOperand(1).getReg();
674 if (!Reg.isVirtual())
680 if (
MI->getOpcode() !=
LMC->MovOpc)
683 if (!
MI->getOperand(1).isImm())
686 int64_t
Imm =
MI->getOperand(1).getImm();
704 if (MO.isReg() && MO.getReg() == AMDGPU::SCC) {
717 auto InsertionPt =
MBB.getFirstTerminator();
718 bool TerminatorsUseSCC =
false;
719 for (
auto I = InsertionPt,
E =
MBB.end();
I !=
E; ++
I) {
722 if (TerminatorsUseSCC || DefsSCC)
726 if (!TerminatorsUseSCC)
729 while (InsertionPt !=
MBB.begin()) {
743void Vreg1LoweringHelper::markAsLaneMask(
Register DstReg)
const {
747void Vreg1LoweringHelper::getCandidatesForLowering(
751 if (isVreg1(
MI.getOperand(0).getReg()))
757void Vreg1LoweringHelper::collectIncomingValuesFromPhi(
758 const MachineInstr *
MI,
759 SmallVectorImpl<AMDGPU::Incoming> &Incomings)
const {
760 for (
unsigned i = 1; i <
MI->getNumOperands(); i += 2) {
761 assert(i + 1 <
MI->getNumOperands());
762 Register IncomingReg =
MI->getOperand(i).getReg();
763 MachineBasicBlock *IncomingMBB =
MI->getOperand(i + 1).getMBB();
766 if (IncomingDef->
getOpcode() == AMDGPU::COPY) {
768 assert(isLaneMaskReg(IncomingReg) || isVreg1(IncomingReg));
770 }
else if (IncomingDef->
getOpcode() == AMDGPU::IMPLICIT_DEF) {
773 assert(IncomingDef->
isPHI() || PhiRegisters.count(IncomingReg));
781 MachineBasicBlock *
MBB) {
785void Vreg1LoweringHelper::buildMergeLaneMasks(MachineBasicBlock &
MBB,
790 bool PrevVal =
false;
791 bool PrevConstant = isConstantLaneMask(PrevReg, PrevVal);
793 bool CurConstant = isConstantLaneMask(CurReg, CurVal);
795 if (PrevConstant && CurConstant) {
796 if (PrevVal == CurVal) {
812 if (CurConstant && CurVal) {
813 PrevMaskedReg = PrevReg;
824 if (PrevConstant && PrevVal) {
825 CurMaskedReg = CurReg;
835 if (PrevConstant && !PrevVal) {
838 }
else if (CurConstant && !CurVal) {
841 }
else if (PrevConstant && PrevVal) {
849 .
addReg(CurMaskedReg ? CurMaskedReg : LMC->ExecReg)
854void Vreg1LoweringHelper::constrainAsLaneMask(AMDGPU::Incoming &In) {}
871 Vreg1LoweringHelper Helper(MF, MDT, MPDT);
873 Changed |= Helper.lowerCopiesFromI1();
875 Changed |= Helper.lowerCopiesToI1();
876 return Helper.cleanConstrainRegs(
Changed);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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 void instrDefsUsesSCC(const MachineInstr &MI, bool &Def, bool &Use)
static Register insertUndefLaneMask(MachineBasicBlock *MBB, MachineRegisterInfo *MRI, MachineRegisterInfo::VRegAttrs LaneMaskRegAttrs)
static bool runFixI1Copies(MachineFunction &MF, MachineDominatorTree &MDT, MachinePostDominatorTree &MPDT)
Lower all instructions that def or use vreg_1 registers.
static bool isVRegCompatibleReg(const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI, Register Reg)
Interface definition of the PhiLoweringHelper class that implements lane mask merging algorithm for d...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Helper class that detects loops which require us to lower an i1 COPY into bitwise manipulation.
void initialize(MachineBasicBlock &MBB)
unsigned findLoop(MachineBasicBlock *PostDom)
Check whether a backward edge can be reached without going through the given PostDom of the def block...
LoopFinder(MachineDominatorTree &DT, MachinePostDominatorTree &PDT)
void addLoopEntries(unsigned LoopLevel, MachineIDFSSAUpdater &SSAUpdater, MachineRegisterInfo &MRI, MachineRegisterInfo::VRegAttrs LaneMaskRegAttrs, ArrayRef< AMDGPU::Incoming > Incomings={})
Add undef values dominating the loop and the optionally given additional blocks, so that the SSA upda...
Helper class that determines the relationship between incoming values of a phi in the control flow gr...
bool isSource(MachineBasicBlock &MBB) const
Returns whether MBB is a source in the induced subgraph of reachable blocks.
ArrayRef< MachineBasicBlock * > predecessors() const
PhiIncomingAnalysis(MachinePostDominatorTree &PDT, const SIInstrInfo *TII)
void analyze(MachineBasicBlock &DefBlock, ArrayRef< AMDGPU::Incoming > Incomings)
bool isLaneMaskReg(Register Reg) const
virtual void replaceDstReg(Register NewReg, Register OldReg, MachineBasicBlock *MBB)=0
MachineBasicBlock::iterator getSaluInsertionAtEnd(MachineBasicBlock &MBB) const
Return a point at the end of the given MBB to insert SALU instructions for lane mask calculation.
bool isConstantLaneMask(Register Reg, bool &Val) const
MachineRegisterInfo::VRegAttrs LaneMaskRegAttrs
void initializeLaneMaskRegisterAttributes(Register LaneMask)
virtual void buildMergeLaneMasks(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DstReg, Register PrevReg, Register CurReg)=0
virtual void getCandidatesForLowering(SmallVectorImpl< MachineInstr * > &Vreg1Phis) const =0
const AMDGPU::LaneMaskConstants * LMC
PhiLoweringHelper(MachineFunction &MF, MachineDominatorTree &DT, MachinePostDominatorTree &PDT)
MachineRegisterInfo * MRI
MachineDominatorTree & DT
DenseSet< Register > PhiRegisters
virtual void markAsLaneMask(Register DstReg) const =0
virtual void constrainAsLaneMask(Incoming &In)=0
virtual void collectIncomingValuesFromPhi(const MachineInstr *MI, SmallVectorImpl< Incoming > &Incomings) const =0
void mergeIncomingLaneMasks(Register DstReg, MachineBasicBlock &MBB, SmallVectorImpl< Incoming > &Incomings, MachineIDFSSAUpdater &SSAUpdater, LoopFinder &LF, PhiIncomingAnalysis &PIA)
Merge the Incomings lane masks into DstReg, the value owned by MBB.
MachinePostDominatorTree & PDT
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()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents analyses that only rely on functions' control flow.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
DomTreeNodeBase * getIDom() const
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
FunctionPass class - This class is used to implement most global optimizations.
const HexagonRegisterInfo & getRegisterInfo() const
void push_back(MachineInstr *MI)
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
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...
MachineFunctionPass(char &ID)
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.
const MachineFunctionProperties & getProperties() const
Get the function properties.
LLVM_ABI Register getValueInMiddleOfBlock(MachineBasicBlock *BB)
See SSAUpdater::GetValueInMiddleOfBlock description.
void addAvailableValue(MachineBasicBlock *BB, Register V)
Indicate that a rewritten value is available in the specified block with the specified value.
LLVM_ABI void calculate()
Calculate and insert necessary PHI nodes for SSA form.
void addUseBlock(MachineBasicBlock *BB)
Record a basic block that uses the value.
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
Register getReg() const
getReg - Returns the register number.
MachinePostDominatorTree - an analysis pass wrapper for DominatorTree used to compute the post-domina...
LLVM_ABI MachineBasicBlock * findNearestCommonDominator(ArrayRef< MachineBasicBlock * > Blocks) const
Returns the nearest common dominator of the given blocks.
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...
LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)
setRegClass - Set the register class of the specified virtual register.
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
This class implements a map that also provides access to all stored values in a deterministic order.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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.
A Use represents the edge between a Value definition and its users.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Register createLaneMaskReg(MachineRegisterInfo *MRI, MachineRegisterInfo::VRegAttrs LaneMaskRegAttrs)
NodeAddr< UseNode * > Use
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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
ArrayRef(const T &OneElt) -> ArrayRef< T >
FunctionPass * createSILowerI1CopiesLegacyPass()
char & SILowerI1CopiesLegacyID
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Incoming for lane mask phi as machine instruction, incoming register Reg and incoming block Block are...
MachineBasicBlock * Block
All attributes(register class or bank and low-level type) a virtual register can have.