74 #define DEBUG_TYPE "si-lower-control-flow" 90 unsigned Andn2TermOpc;
92 unsigned OrSaveExecOpc;
116 return "SI Lower control flow pseudo instructions";
136 "SI lower control flow",
false,
false)
165 while (!Worklist.empty()) {
168 if (MBB == EMBB || !Visited.
insert(MBB).second)
186 unsigned FalseTermOpc =
187 TII->isWave32() ? AMDGPU::S_MOV_B32_term : AMDGPU::S_MOV_B64_term;
190 if (J != MBB->
end() && J->getOpcode() == FalseTermOpc &&
191 J->getOperand(1).isReg() && J->getOperand(1).getReg() == SaveExecReg) {
192 SaveExecReg = J->getOperand(0).getReg();
193 J->eraseFromParent();
202 Register SaveExecReg = getSaveExec(&MI);
207 assert(ImpDefSCC.getReg() == AMDGPU::SCC && ImpDefSCC.isDef());
216 Register CopyReg = SimpleIf ? SaveExecReg
217 :
MRI->createVirtualRegister(BoolRC);
219 BuildMI(MBB, I, DL,
TII->get(AMDGPU::COPY), CopyReg)
230 setImpSCCDefDead(*And,
true);
235 BuildMI(MBB, I, DL,
TII->get(XorOpc), SaveExecReg)
238 setImpSCCDefDead(*Xor, ImpDefSCC.isDead());
244 BuildMI(MBB, I, DL,
TII->get(MovTermOpc), Exec)
257 LIS->InsertMachineInstrInMaps(*CopyExec);
261 LIS->ReplaceMachineInstrInMaps(MI, *And);
264 LIS->InsertMachineInstrInMaps(*Xor);
265 LIS->InsertMachineInstrInMaps(*SetExec);
266 LIS->InsertMachineInstrInMaps(*NewBr);
268 LIS->removeAllRegUnitsForPhysReg(AMDGPU::EXEC);
274 LIS->removeInterval(SaveExecReg);
275 LIS->createAndComputeVirtRegInterval(SaveExecReg);
276 LIS->createAndComputeVirtRegInterval(Tmp);
278 LIS->createAndComputeVirtRegInterval(CopyReg);
293 Register CopyReg =
MRI->createVirtualRegister(BoolRC);
295 BuildMI(MBB, Start, DL,
TII->get(AMDGPU::COPY), CopyReg)
301 MRI->createVirtualRegister(BoolRC) : DstReg;
303 BuildMI(MBB, Start, DL,
TII->get(OrSaveExecOpc), SaveReg)
312 BuildMI(MBB, ElsePt, DL,
TII->get(AndOpc), DstReg)
317 LIS->InsertMachineInstrInMaps(*And);
321 BuildMI(MBB, ElsePt, DL,
TII->get(XorTermrOpc), Exec)
326 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::SI_MASK_BRANCH))
334 LIS->RemoveMachineInstrFromMaps(MI);
337 LIS->InsertMachineInstrInMaps(*CopyExec);
338 LIS->InsertMachineInstrInMaps(*OrSaveExec);
340 LIS->InsertMachineInstrInMaps(*Xor);
341 LIS->InsertMachineInstrInMaps(*Branch);
344 LIS->removeInterval(DstReg);
345 LIS->createAndComputeVirtRegInterval(DstReg);
346 LIS->createAndComputeVirtRegInterval(CopyReg);
348 LIS->createAndComputeVirtRegInterval(SaveReg);
351 LIS->removeAllRegUnitsForPhysReg(AMDGPU::EXEC);
354 void SILowerControlFlow::emitIfBreak(
MachineInstr &MI) {
357 auto Dst = getSaveExec(&MI);
363 bool SkipAnding =
false;
375 And =
BuildMI(MBB, &MI, DL,
TII->get(AndOpc), Dst)
378 Or =
BuildMI(MBB, &MI, DL,
TII->get(OrOpc), Dst)
382 Or =
BuildMI(MBB, &MI, DL,
TII->get(OrOpc), Dst)
388 LIS->InsertMachineInstrInMaps(*And);
389 LIS->ReplaceMachineInstrInMaps(MI, *Or);
400 BuildMI(MBB, &MI, DL,
TII->get(Andn2TermOpc), Exec)
405 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_CBRANCH_EXECNZ))
409 LIS->ReplaceMachineInstrInMaps(MI, *AndN2);
410 LIS->InsertMachineInstrInMaps(*Branch);
431 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
436 LIS->handleMove(*NewMI);
441 void SILowerControlFlow::findMaskOperands(
MachineInstr &MI,
unsigned OpNo,
458 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI) &&
459 !(
I->isCopy() &&
I->getOperand(0).getReg() != Exec))
472 void SILowerControlFlow::combineMasks(
MachineInstr &MI) {
475 unsigned OpToReplace = 1;
476 findMaskOperands(MI, 1, Ops);
477 if (Ops.size() == 1) OpToReplace = 2;
478 findMaskOperands(MI, 2, Ops);
479 if (Ops.size() != 3)
return;
481 unsigned UniqueOpndIdx;
482 if (Ops[0].isIdenticalTo(Ops[1])) UniqueOpndIdx = 2;
483 else if (Ops[0].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
484 else if (Ops[1].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
490 if (
MRI->use_empty(Reg))
491 MRI->getUniqueVRegDef(Reg)->eraseFromParent();
500 LIS = getAnalysisIfAvailable<LiveIntervals>();
502 BoolRC =
TRI->getBoolRC();
505 AndOpc = AMDGPU::S_AND_B32;
506 OrOpc = AMDGPU::S_OR_B32;
507 XorOpc = AMDGPU::S_XOR_B32;
508 MovTermOpc = AMDGPU::S_MOV_B32_term;
509 Andn2TermOpc = AMDGPU::S_ANDN2_B32_term;
510 XorTermrOpc = AMDGPU::S_XOR_B32_term;
511 OrSaveExecOpc = AMDGPU::S_OR_SAVEEXEC_B32;
512 Exec = AMDGPU::EXEC_LO;
514 AndOpc = AMDGPU::S_AND_B64;
515 OrOpc = AMDGPU::S_OR_B64;
516 XorOpc = AMDGPU::S_XOR_B64;
517 MovTermOpc = AMDGPU::S_MOV_B64_term;
518 Andn2TermOpc = AMDGPU::S_ANDN2_B64_term;
519 XorTermrOpc = AMDGPU::S_XOR_B64_term;
520 OrSaveExecOpc = AMDGPU::S_OR_SAVEEXEC_B64;
526 BI != BE; BI = NextBB) {
527 NextBB = std::next(BI);
532 for (I = MBB.
begin(), Last = MBB.
end(); I != MBB.
end(); I = Next) {
541 case AMDGPU::SI_ELSE:
545 case AMDGPU::SI_IF_BREAK:
549 case AMDGPU::SI_LOOP:
553 case AMDGPU::SI_END_CF:
557 case AMDGPU::S_AND_B64:
558 case AMDGPU::S_OR_B64:
559 case AMDGPU::S_AND_B32:
560 case AMDGPU::S_OR_B32:
572 Next = (Last == MBB.
end()) ? MBB.
begin() : Last;
const MachineInstrBuilder & add(const MachineOperand &MO) const
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
AMDGPU specific subclass of TargetSubtarget.
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
iterator_range< mop_iterator > explicit_operands()
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
unsigned getSubReg() const
INITIALIZE_PASS(SILowerControlFlow, DEBUG_TYPE, "SI lower control flow", false, false) static void setImpSCCDefDead(MachineInstr &MI
const SIInstrInfo * getInstrInfo() const override
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
iterator_range< iterator > terminators()
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static bool isVALU(const MachineInstr &MI)
AnalysisUsage & addPreservedID(const void *ID)
char & LiveVariablesID
LiveVariables pass - This pass computes the set of blocks in which each variable is life and sets mac...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
std::pair< iterator, bool > insert(const ValueT &V)
Represent the analysis usage information of a pass.
self_iterator getIterator()
succ_iterator succ_begin()
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
Iterator for intrusive lists based on ilist_node.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
MachineInstr * getUniqueVRegDef(unsigned Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
char & SILowerControlFlowID
static bool isSimpleIf(const MachineInstr &MI, const MachineRegisterInfo *MRI, const SIInstrInfo *TII)
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Interface definition for SIInstrInfo.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static use_instr_nodbg_iterator use_instr_nodbg_end()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
StringRef - Represent a constant reference to a string, i.e.
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
Register getReg() const
getReg - Returns the register number.
static bool isKillTerminator(unsigned Opcode)
const MachineOperand & getOperand(unsigned i) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Wrapper class representing virtual and physical registers.
const SIRegisterInfo * getRegisterInfo() const override