64 #define DEBUG_TYPE "si-lower-control-flow"
91 SILowerControlFlow() :
101 return "SI Lower control flow pseudo instructions";
121 "SI lower control flow",
false,
false)
140 Cond.
getSubReg() == AMDGPU::NoSubRegister);
142 unsigned SaveExecReg = SaveExec.
getReg();
149 unsigned CopyReg =
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
151 BuildMI(MBB, I, DL,
TII->get(AMDGPU::COPY), CopyReg)
152 .addReg(AMDGPU::EXEC)
155 unsigned Tmp =
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
158 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_AND_B64), Tmp)
162 setImpSCCDefDead(*And,
true);
165 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_XOR_B64), SaveExecReg)
168 setImpSCCDefDead(*Xor, ImpDefSCC.
isDead());
173 BuildMI(MBB, I, DL,
TII->get(AMDGPU::S_MOV_B64_term), AMDGPU::EXEC)
179 BuildMI(MBB, I, DL,
TII->get(AMDGPU::SI_MASK_BRANCH))
187 LIS->InsertMachineInstrInMaps(*CopyExec);
191 LIS->ReplaceMachineInstrInMaps(MI, *And);
193 LIS->InsertMachineInstrInMaps(*Xor);
194 LIS->InsertMachineInstrInMaps(*SetExec);
195 LIS->InsertMachineInstrInMaps(*NewBr);
203 LIS->removeInterval(SaveExecReg);
204 LIS->createAndComputeVirtRegInterval(SaveExecReg);
205 LIS->createAndComputeVirtRegInterval(Tmp);
206 LIS->createAndComputeVirtRegInterval(CopyReg);
222 unsigned CopyReg =
MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
223 BuildMI(MBB, Start, DL,
TII->get(AMDGPU::COPY), CopyReg)
228 unsigned SaveReg = ExecModified ?
229 MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass) : DstReg;
231 BuildMI(MBB, Start, DL,
TII->get(AMDGPU::S_OR_SAVEEXEC_B64), SaveReg)
240 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::S_AND_B64), DstReg)
241 .addReg(AMDGPU::EXEC)
245 LIS->InsertMachineInstrInMaps(*And);
249 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::S_XOR_B64_term), AMDGPU::EXEC)
250 .addReg(AMDGPU::EXEC)
254 BuildMI(MBB, ElsePt, DL,
TII->get(AMDGPU::SI_MASK_BRANCH))
262 LIS->RemoveMachineInstrFromMaps(MI);
265 LIS->InsertMachineInstrInMaps(*OrSaveExec);
267 LIS->InsertMachineInstrInMaps(*Xor);
268 LIS->InsertMachineInstrInMaps(*Branch);
271 LIS->removeInterval(DstReg);
272 LIS->createAndComputeVirtRegInterval(DstReg);
273 LIS->createAndComputeVirtRegInterval(CopyReg);
275 LIS->createAndComputeVirtRegInterval(SaveReg);
287 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_OR_B64), Dst)
288 .addReg(AMDGPU::EXEC)
292 LIS->ReplaceMachineInstrInMaps(MI, *Or);
296 void SILowerControlFlow::emitIfBreak(
MachineInstr &MI) {
300 void SILowerControlFlow::emitElseBreak(
MachineInstr &MI) {
309 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_ANDN2_B64_term), AMDGPU::EXEC)
310 .addReg(AMDGPU::EXEC)
314 BuildMI(MBB, &MI, DL,
TII->get(AMDGPU::S_CBRANCH_EXECNZ))
318 LIS->ReplaceMachineInstrInMaps(MI, *AndN2);
319 LIS->InsertMachineInstrInMaps(*Branch);
331 BuildMI(MBB, InsPt, DL,
TII->get(AMDGPU::S_OR_B64), AMDGPU::EXEC)
332 .addReg(AMDGPU::EXEC)
336 LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
341 LIS->handleMove(*NewMI);
346 void SILowerControlFlow::findMaskOperands(
MachineInstr &MI,
unsigned OpNo,
363 if (
I->modifiesRegister(AMDGPU::EXEC, TRI) &&
364 !(
I->isCopy() &&
I->getOperand(0).getReg() != AMDGPU::EXEC))
368 if (SrcOp.isUse() && (!SrcOp.isReg() ||
370 SrcOp.getReg() == AMDGPU::EXEC))
378 void SILowerControlFlow::combineMasks(
MachineInstr &MI) {
381 unsigned OpToReplace = 1;
382 findMaskOperands(MI, 1, Ops);
383 if (Ops.size() == 1) OpToReplace = 2;
384 findMaskOperands(MI, 2, Ops);
385 if (Ops.size() != 3)
return;
387 unsigned UniqueOpndIdx;
388 if (Ops[0].isIdenticalTo(Ops[1])) UniqueOpndIdx = 2;
389 else if (Ops[0].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
390 else if (Ops[1].isIdenticalTo(Ops[2])) UniqueOpndIdx = 1;
396 if (
MRI->use_empty(Reg))
397 MRI->getUniqueVRegDef(Reg)->eraseFromParent();
406 LIS = getAnalysisIfAvailable<LiveIntervals>();
411 BI != BE; BI = NextBB) {
412 NextBB = std::next(BI);
417 for (I = MBB.
begin(), Last = MBB.
end(); I != MBB.
end(); I = Next) {
426 case AMDGPU::SI_ELSE:
430 case AMDGPU::SI_BREAK:
434 case AMDGPU::SI_IF_BREAK:
438 case AMDGPU::SI_ELSE_BREAK:
442 case AMDGPU::SI_LOOP:
446 case AMDGPU::SI_END_CF:
450 case AMDGPU::S_AND_B64:
451 case AMDGPU::S_OR_B64:
463 Next = (Last == MBB.
end()) ? MBB.
begin() : Last;
void push_back(const T &Elt)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
AMDGPU specific subclass of TargetSubtarget.
MachineBasicBlock * getMBB() const
iterator_range< mop_iterator > explicit_operands()
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
const SIInstrInfo * getInstrInfo() const override
void setIsDead(bool Val=true)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Reg
All possible values of the reg field in the ModR/M byte.
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
AnalysisUsage & addPreservedID(const void *ID)
bool IsDead MachineOperand & ImpDefSCC
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
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
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineOperand & getOperand(unsigned i) const
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
APInt Xor(const APInt &LHS, const APInt &RHS)
Bitwise XOR function for APInt.
Represent the analysis usage information of a pass.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
self_iterator getIterator()
unsigned getSubReg() const
Iterator for intrusive lists based on ilist_node.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
const SIRegisterInfo * getRegisterInfo() const override
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:
INITIALIZE_PASS(SILowerControlFlow, DEBUG_TYPE,"SI lower control flow", false, false) static void setImpSCCDefDead(MachineInstr &MI
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
char & SILowerControlFlowID
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Interface definition for SIInstrInfo.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
StringRef - Represent a constant reference to a string, i.e.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.