75 #define DEBUG_TYPE "si-lower-control-flow" 105 return "SI Lower control flow pseudo instructions";
125 "SI lower control flow",
false,
false)
154 while (!Worklist.empty()) {
157 if (MBB == EMBB || !Visited.
insert(MBB).second)
177 Cond.
getSubReg() == AMDGPU::NoSubRegister);
179 unsigned SaveExecReg = SaveExec.
getReg();
191 unsigned CopyReg = SimpleIf ? SaveExecReg
192 :
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
194 BuildMI(MBB, I, DL,
TII->get(AMDGPU::COPY), CopyReg)
195 .addReg(AMDGPU::EXEC)
198 unsigned Tmp =
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
201 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_AND_B64), Tmp)
205 setImpSCCDefDead(*And,
true);
210 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_XOR_B64), SaveExecReg)
213 setImpSCCDefDead(*Xor, ImpDefSCC.
isDead());
219 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_MOV_B64_term), AMDGPU::EXEC)
232 LIS->InsertMachineInstrInMaps(*CopyExec);
236 LIS->ReplaceMachineInstrInMaps(MI, *And);
239 LIS->InsertMachineInstrInMaps(*Xor);
240 LIS->InsertMachineInstrInMaps(*SetExec);
241 LIS->InsertMachineInstrInMaps(*NewBr);
249 LIS->removeInterval(SaveExecReg);
250 LIS->createAndComputeVirtRegInterval(SaveExecReg);
251 LIS->createAndComputeVirtRegInterval(Tmp);
253 LIS->createAndComputeVirtRegInterval(CopyReg);
269 unsigned CopyReg =
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
271 BuildMI(MBB, Start, DL,
TII->get(AMDGPU::COPY), CopyReg)
276 unsigned SaveReg = ExecModified ?
277 MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass) : DstReg;
279 BuildMI(MBB, Start, DL,
TII->get(AMDGPU::S_OR_SAVEEXEC_B64), SaveReg)
288 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::S_AND_B64), DstReg)
289 .addReg(AMDGPU::EXEC)
293 LIS->InsertMachineInstrInMaps(*And);
297 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::S_XOR_B64_term), AMDGPU::EXEC)
298 .addReg(AMDGPU::EXEC)
302 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::SI_MASK_BRANCH))
310 LIS->RemoveMachineInstrFromMaps(MI);
313 LIS->InsertMachineInstrInMaps(*CopyExec);
314 LIS->InsertMachineInstrInMaps(*OrSaveExec);
316 LIS->InsertMachineInstrInMaps(*Xor);
317 LIS->InsertMachineInstrInMaps(*Branch);
320 LIS->removeInterval(DstReg);
321 LIS->createAndComputeVirtRegInterval(DstReg);
322 LIS->createAndComputeVirtRegInterval(CopyReg);
324 LIS->createAndComputeVirtRegInterval(SaveReg);
330 void SILowerControlFlow::emitIfBreak(
MachineInstr &MI) {
339 bool SkipAnding =
false;
351 And =
BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_AND_B64), Dst)
352 .addReg(AMDGPU::EXEC)
354 Or =
BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_OR_B64), Dst)
358 Or =
BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_OR_B64), Dst)
364 LIS->InsertMachineInstrInMaps(*And);
365 LIS->ReplaceMachineInstrInMaps(MI, *Or);
376 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_ANDN2_B64_term), AMDGPU::EXEC)
377 .addReg(AMDGPU::EXEC)
381 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_CBRANCH_EXECNZ))
385 LIS->ReplaceMachineInstrInMaps(MI, *AndN2);
386 LIS->InsertMachineInstrInMaps(*Branch);
398 BuildMI(MBB, InsPt, DL,
TII->get(AMDGPU::S_OR_B64), AMDGPU::EXEC)
399 .addReg(AMDGPU::EXEC)
403 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
408 LIS->handleMove(*NewMI);
413 void SILowerControlFlow::findMaskOperands(
MachineInstr &MI,
unsigned OpNo,
430 if (
I->modifiesRegister(AMDGPU::EXEC,
TRI) &&
431 !(
I->isCopy() &&
I->getOperand(0).getReg() != AMDGPU::EXEC))
445 void SILowerControlFlow::combineMasks(
MachineInstr &MI) {
448 unsigned OpToReplace = 1;
449 findMaskOperands(MI, 1, Ops);
450 if (Ops.size() == 1) OpToReplace = 2;
451 findMaskOperands(MI, 2, Ops);
452 if (Ops.size() != 3)
return;
454 unsigned UniqueOpndIdx;
455 if (Ops[0].isIdenticalTo(Ops[1])) UniqueOpndIdx = 2;
456 else if (Ops[0].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
457 else if (Ops[1].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
463 if (
MRI->use_empty(Reg))
464 MRI->getUniqueVRegDef(Reg)->eraseFromParent();
473 LIS = getAnalysisIfAvailable<LiveIntervals>();
478 BI != BE; BI = NextBB) {
479 NextBB = std::next(BI);
484 for (I = MBB.
begin(), Last = MBB.
end(); I != MBB.
end(); I = Next) {
493 case AMDGPU::SI_ELSE:
497 case AMDGPU::SI_IF_BREAK:
501 case AMDGPU::SI_LOOP:
505 case AMDGPU::SI_END_CF:
509 case AMDGPU::S_AND_B64:
510 case AMDGPU::S_OR_B64:
522 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 getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
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.
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:
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.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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
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...
static bool isKillTerminator(unsigned Opcode)
const MachineOperand & getOperand(unsigned i) const
const SIRegisterInfo * getRegisterInfo() const override