LLVM  12.0.0git
SIInsertSkips.cpp
Go to the documentation of this file.
1 //===-- SIInsertSkips.cpp - Use predicates for control flow ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// This pass inserts branches on the 0 exec mask over divergent branches
11 /// branches when it's expected that jumping over the untaken control flow will
12 /// be cheaper than having every workitem no-op through it.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "AMDGPU.h"
17 #include "AMDGPUSubtarget.h"
20 #include "llvm/InitializePasses.h"
21 
22 using namespace llvm;
23 
24 #define DEBUG_TYPE "si-insert-skips"
25 
27  "amdgpu-skip-threshold-legacy",
28  cl::desc("Number of instructions before jumping over divergent control flow"),
29  cl::init(12), cl::Hidden);
30 
31 namespace {
32 
33 class SIInsertSkips : public MachineFunctionPass {
34 private:
35  const SIRegisterInfo *TRI = nullptr;
36  const SIInstrInfo *TII = nullptr;
37  unsigned SkipThreshold = 0;
38  MachineDominatorTree *MDT = nullptr;
39 
40  MachineBasicBlock *EarlyExitBlock = nullptr;
41  bool EarlyExitClearsExec = false;
42 
43  bool shouldSkip(const MachineBasicBlock &From,
44  const MachineBasicBlock &To) const;
45 
46  bool dominatesAllReachable(MachineBasicBlock &MBB);
47  void ensureEarlyExitBlock(MachineBasicBlock &MBB, bool ClearExec);
49  DebugLoc DL);
50 
51  bool kill(MachineInstr &MI);
52  void earlyTerm(MachineInstr &MI);
53 
54  bool skipMaskBranch(MachineInstr &MI, MachineBasicBlock &MBB);
55 
56 public:
57  static char ID;
58 
59  SIInsertSkips() : MachineFunctionPass(ID) {}
60 
61  bool runOnMachineFunction(MachineFunction &MF) override;
62 
63  StringRef getPassName() const override {
64  return "SI insert s_cbranch_execz instructions";
65  }
66 
67  void getAnalysisUsage(AnalysisUsage &AU) const override {
71  }
72 };
73 
74 } // end anonymous namespace
75 
76 char SIInsertSkips::ID = 0;
77 
78 INITIALIZE_PASS_BEGIN(SIInsertSkips, DEBUG_TYPE,
79  "SI insert s_cbranch_execz instructions", false, false)
82  "SI insert s_cbranch_execz instructions", false, false)
83 
84 char &llvm::SIInsertSkipsPassID = SIInsertSkips::ID;
85 
87  if (MI.isMetaInstruction())
88  return true;
89 
90  // Handle target specific opcodes.
91  switch (MI.getOpcode()) {
92  case AMDGPU::SI_MASK_BRANCH:
93  return true;
94  default:
95  return false;
96  }
97 }
98 
99 bool SIInsertSkips::shouldSkip(const MachineBasicBlock &From,
100  const MachineBasicBlock &To) const {
101  unsigned NumInstr = 0;
102  const MachineFunction *MF = From.getParent();
103 
104  for (MachineFunction::const_iterator MBBI(&From), ToI(&To), End = MF->end();
105  MBBI != End && MBBI != ToI; ++MBBI) {
106  const MachineBasicBlock &MBB = *MBBI;
107 
109  NumInstr < SkipThreshold && I != E; ++I) {
110  if (opcodeEmitsNoInsts(*I))
111  continue;
112 
113  // FIXME: Since this is required for correctness, this should be inserted
114  // during SILowerControlFlow.
115 
116  // When a uniform loop is inside non-uniform control flow, the branch
117  // leaving the loop might be an S_CBRANCH_VCCNZ, which is never taken
118  // when EXEC = 0. We should skip the loop lest it becomes infinite.
119  if (I->getOpcode() == AMDGPU::S_CBRANCH_VCCNZ ||
120  I->getOpcode() == AMDGPU::S_CBRANCH_VCCZ)
121  return true;
122 
123  if (TII->hasUnwantedEffectsWhenEXECEmpty(*I))
124  return true;
125 
126  // These instructions are potentially expensive even if EXEC = 0.
127  if (TII->isSMRD(*I) || TII->isVMEM(*I) || TII->isFLAT(*I) ||
128  I->getOpcode() == AMDGPU::S_WAITCNT)
129  return true;
130 
131  ++NumInstr;
132  if (NumInstr >= SkipThreshold)
133  return true;
134  }
135  }
136 
137  return false;
138 }
139 
140 /// Check whether \p MBB dominates all blocks that are reachable from it.
141 bool SIInsertSkips::dominatesAllReachable(MachineBasicBlock &MBB) {
142  for (MachineBasicBlock *Other : depth_first(&MBB)) {
143  if (!MDT->dominates(&MBB, Other))
144  return false;
145  }
146  return true;
147 }
148 
151  const SIInstrInfo *TII, bool IsPS) {
152  // "null export"
153  if (IsPS) {
154  BuildMI(MBB, I, DL, TII->get(AMDGPU::EXP_DONE))
155  .addImm(AMDGPU::Exp::ET_NULL)
156  .addReg(AMDGPU::VGPR0, RegState::Undef)
157  .addReg(AMDGPU::VGPR0, RegState::Undef)
158  .addReg(AMDGPU::VGPR0, RegState::Undef)
159  .addReg(AMDGPU::VGPR0, RegState::Undef)
160  .addImm(1) // vm
161  .addImm(0) // compr
162  .addImm(0); // en
163  }
164  // s_endpgm
165  BuildMI(MBB, I, DL, TII->get(AMDGPU::S_ENDPGM)).addImm(0);
166 }
167 
168 void SIInsertSkips::ensureEarlyExitBlock(MachineBasicBlock &MBB,
169  bool ClearExec) {
170  MachineFunction *MF = MBB.getParent();
171  DebugLoc DL;
172 
173  if (!EarlyExitBlock) {
174  EarlyExitBlock = MF->CreateMachineBasicBlock();
175  MF->insert(MF->end(), EarlyExitBlock);
176  generateEndPgm(*EarlyExitBlock, EarlyExitBlock->end(), DL, TII,
177  MF->getFunction().getCallingConv() ==
179  EarlyExitClearsExec = false;
180  }
181 
182  if (ClearExec && !EarlyExitClearsExec) {
183  const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
184  unsigned Mov = ST.isWave32() ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64;
185  Register Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
186  auto ExitI = EarlyExitBlock->getFirstNonPHI();
187  BuildMI(*EarlyExitBlock, ExitI, DL, TII->get(Mov), Exec).addImm(0);
188  EarlyExitClearsExec = true;
189  }
190 }
191 
193  MachineDominatorTree *MDT) {
194  MachineBasicBlock *SplitBB = MBB.splitAt(MI, /*UpdateLiveIns*/ true);
195 
196  // Update dominator tree
197  using DomTreeT = DomTreeBase<MachineBasicBlock>;
199  for (MachineBasicBlock *Succ : SplitBB->successors()) {
200  DTUpdates.push_back({DomTreeT::Insert, SplitBB, Succ});
201  DTUpdates.push_back({DomTreeT::Delete, &MBB, Succ});
202  }
203  DTUpdates.push_back({DomTreeT::Insert, &MBB, SplitBB});
204  MDT->getBase().applyUpdates(DTUpdates);
205 }
206 
207 /// Insert an "if exec=0 { null export; s_endpgm }" sequence before the given
208 /// iterator. Only applies to pixel shaders.
209 void SIInsertSkips::skipIfDead(MachineBasicBlock &MBB,
211  MachineFunction *MF = MBB.getParent();
212  (void)MF;
214 
215  // It is possible for an SI_KILL_*_TERMINATOR to sit at the bottom of a
216  // basic block that has no further successors (e.g., there was an
217  // `unreachable` there in IR). This can happen with original source of the
218  // form:
219  //
220  // if (uniform_condition) {
221  // write_to_memory();
222  // discard;
223  // }
224  //
225  // In this case, we write the "null_export; s_endpgm" skip code in the
226  // already-existing basic block.
227  auto NextBBI = std::next(MBB.getIterator());
228  bool NoSuccessor =
229  I == MBB.end() && !llvm::is_contained(MBB.successors(), &*NextBBI);
230 
231  if (NoSuccessor) {
232  generateEndPgm(MBB, I, DL, TII, true);
233  } else {
234  ensureEarlyExitBlock(MBB, false);
235 
236  MachineInstr *BranchMI =
237  BuildMI(MBB, I, DL, TII->get(AMDGPU::S_CBRANCH_EXECZ))
238  .addMBB(EarlyExitBlock);
239 
240  // Split the block if the branch will not come at the end.
241  auto Next = std::next(BranchMI->getIterator());
242  if (Next != MBB.end() && !Next->isTerminator())
243  splitBlock(MBB, *BranchMI, MDT);
244 
245  MBB.addSuccessor(EarlyExitBlock);
246  MDT->getBase().insertEdge(&MBB, EarlyExitBlock);
247  }
248 }
249 
250 /// Translate a SI_KILL_*_TERMINATOR into exec-manipulating instructions.
251 /// Return true unless the terminator is a no-op.
252 bool SIInsertSkips::kill(MachineInstr &MI) {
253  MachineBasicBlock &MBB = *MI.getParent();
254  DebugLoc DL = MI.getDebugLoc();
255 
256  switch (MI.getOpcode()) {
257  case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR: {
258  unsigned Opcode = 0;
259 
260  // The opcodes are inverted because the inline immediate has to be
261  // the first operand, e.g. from "x < imm" to "imm > x"
262  switch (MI.getOperand(2).getImm()) {
263  case ISD::SETOEQ:
264  case ISD::SETEQ:
265  Opcode = AMDGPU::V_CMPX_EQ_F32_e64;
266  break;
267  case ISD::SETOGT:
268  case ISD::SETGT:
269  Opcode = AMDGPU::V_CMPX_LT_F32_e64;
270  break;
271  case ISD::SETOGE:
272  case ISD::SETGE:
273  Opcode = AMDGPU::V_CMPX_LE_F32_e64;
274  break;
275  case ISD::SETOLT:
276  case ISD::SETLT:
277  Opcode = AMDGPU::V_CMPX_GT_F32_e64;
278  break;
279  case ISD::SETOLE:
280  case ISD::SETLE:
281  Opcode = AMDGPU::V_CMPX_GE_F32_e64;
282  break;
283  case ISD::SETONE:
284  case ISD::SETNE:
285  Opcode = AMDGPU::V_CMPX_LG_F32_e64;
286  break;
287  case ISD::SETO:
288  Opcode = AMDGPU::V_CMPX_O_F32_e64;
289  break;
290  case ISD::SETUO:
291  Opcode = AMDGPU::V_CMPX_U_F32_e64;
292  break;
293  case ISD::SETUEQ:
294  Opcode = AMDGPU::V_CMPX_NLG_F32_e64;
295  break;
296  case ISD::SETUGT:
297  Opcode = AMDGPU::V_CMPX_NGE_F32_e64;
298  break;
299  case ISD::SETUGE:
300  Opcode = AMDGPU::V_CMPX_NGT_F32_e64;
301  break;
302  case ISD::SETULT:
303  Opcode = AMDGPU::V_CMPX_NLE_F32_e64;
304  break;
305  case ISD::SETULE:
306  Opcode = AMDGPU::V_CMPX_NLT_F32_e64;
307  break;
308  case ISD::SETUNE:
309  Opcode = AMDGPU::V_CMPX_NEQ_F32_e64;
310  break;
311  default:
312  llvm_unreachable("invalid ISD:SET cond code");
313  }
314 
316  if (ST.hasNoSdstCMPX())
317  Opcode = AMDGPU::getVCMPXNoSDstOp(Opcode);
318 
319  assert(MI.getOperand(0).isReg());
320 
321  if (TRI->isVGPR(MBB.getParent()->getRegInfo(),
322  MI.getOperand(0).getReg())) {
323  Opcode = AMDGPU::getVOPe32(Opcode);
324  BuildMI(MBB, &MI, DL, TII->get(Opcode))
325  .add(MI.getOperand(1))
326  .add(MI.getOperand(0));
327  } else {
328  auto I = BuildMI(MBB, &MI, DL, TII->get(Opcode));
329  if (!ST.hasNoSdstCMPX())
330  I.addReg(AMDGPU::VCC, RegState::Define);
331 
332  I.addImm(0) // src0 modifiers
333  .add(MI.getOperand(1))
334  .addImm(0) // src1 modifiers
335  .add(MI.getOperand(0));
336 
337  I.addImm(0); // omod
338  }
339  return true;
340  }
341  case AMDGPU::SI_KILL_I1_TERMINATOR: {
342  const MachineFunction *MF = MI.getParent()->getParent();
343  const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
344  unsigned Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC;
345  const MachineOperand &Op = MI.getOperand(0);
346  int64_t KillVal = MI.getOperand(1).getImm();
347  assert(KillVal == 0 || KillVal == -1);
348 
349  // Kill all threads if Op0 is an immediate and equal to the Kill value.
350  if (Op.isImm()) {
351  int64_t Imm = Op.getImm();
352  assert(Imm == 0 || Imm == -1);
353 
354  if (Imm == KillVal) {
355  BuildMI(MBB, &MI, DL, TII->get(ST.isWave32() ? AMDGPU::S_MOV_B32
356  : AMDGPU::S_MOV_B64), Exec)
357  .addImm(0);
358  return true;
359  }
360  return false;
361  }
362 
363  unsigned Opcode = KillVal ? AMDGPU::S_ANDN2_B64 : AMDGPU::S_AND_B64;
364  if (ST.isWave32())
365  Opcode = KillVal ? AMDGPU::S_ANDN2_B32 : AMDGPU::S_AND_B32;
366  BuildMI(MBB, &MI, DL, TII->get(Opcode), Exec)
367  .addReg(Exec)
368  .add(Op);
369  return true;
370  }
371  default:
372  llvm_unreachable("invalid opcode, expected SI_KILL_*_TERMINATOR");
373  }
374 }
375 
376 void SIInsertSkips::earlyTerm(MachineInstr &MI) {
377  MachineBasicBlock &MBB = *MI.getParent();
378  const DebugLoc DL = MI.getDebugLoc();
379 
380  ensureEarlyExitBlock(MBB, true);
381 
382  auto BranchMI = BuildMI(MBB, MI, DL, TII->get(AMDGPU::S_CBRANCH_SCC0))
383  .addMBB(EarlyExitBlock);
384  auto Next = std::next(MI.getIterator());
385 
386  if (Next != MBB.end() && !Next->isTerminator())
387  splitBlock(MBB, *BranchMI, MDT);
388 
389  MBB.addSuccessor(EarlyExitBlock);
390  MDT->getBase().insertEdge(&MBB, EarlyExitBlock);
391 }
392 
393 // Returns true if a branch over the block was inserted.
394 bool SIInsertSkips::skipMaskBranch(MachineInstr &MI,
395  MachineBasicBlock &SrcMBB) {
396  MachineBasicBlock *DestBB = MI.getOperand(0).getMBB();
397 
398  if (!shouldSkip(**SrcMBB.succ_begin(), *DestBB))
399  return false;
400 
401  const DebugLoc &DL = MI.getDebugLoc();
402  MachineBasicBlock::iterator InsPt = std::next(MI.getIterator());
403 
404  BuildMI(SrcMBB, InsPt, DL, TII->get(AMDGPU::S_CBRANCH_EXECZ))
405  .addMBB(DestBB);
406 
407  return true;
408 }
409 
410 bool SIInsertSkips::runOnMachineFunction(MachineFunction &MF) {
411  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
412  TII = ST.getInstrInfo();
413  TRI = &TII->getRegisterInfo();
414  MDT = &getAnalysis<MachineDominatorTree>();
416 
418  SmallVector<MachineInstr *, 4> EarlyTermInstrs;
419  bool MadeChange = false;
420 
421  for (MachineBasicBlock &MBB : MF) {
423  for (I = MBB.begin(); I != MBB.end(); I = Next) {
424  Next = std::next(I);
425  MachineInstr &MI = *I;
426 
427  switch (MI.getOpcode()) {
428  case AMDGPU::SI_MASK_BRANCH:
429  MadeChange |= skipMaskBranch(MI, MBB);
430  break;
431 
432  case AMDGPU::S_BRANCH:
433  // Optimize out branches to the next block.
434  // FIXME: Shouldn't this be handled by BranchFolding?
435  if (MBB.isLayoutSuccessor(MI.getOperand(0).getMBB())) {
436  assert(&MI == &MBB.back());
437  MI.eraseFromParent();
438  MadeChange = true;
439  }
440  break;
441 
442  case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
443  case AMDGPU::SI_KILL_I1_TERMINATOR: {
444  MadeChange = true;
445  bool CanKill = kill(MI);
446 
447  // Check if we can add an early "if exec=0 { end shader }".
448  //
449  // Note that we _always_ do this if it is correct, even if the kill
450  // happens fairly late in the shader, because the null export should
451  // generally still be cheaper than normal export(s).
452  //
453  // TODO: The dominatesAllReachable check is conservative: if the
454  // dominance is only missing due to _uniform_ branches, we could
455  // in fact insert the early-exit as well.
456  if (CanKill &&
457  MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS &&
458  dominatesAllReachable(MBB)) {
459  // Mark the instruction for kill-if-dead insertion. We delay this
460  // change because it modifies the CFG.
461  KillInstrs.push_back(&MI);
462  } else {
463  MI.eraseFromParent();
464  }
465  break;
466  }
467 
468  case AMDGPU::SI_KILL_CLEANUP:
469  if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS &&
470  dominatesAllReachable(MBB)) {
471  KillInstrs.push_back(&MI);
472  } else {
473  MI.eraseFromParent();
474  }
475  break;
476 
477  case AMDGPU::SI_EARLY_TERMINATE_SCC0:
478  EarlyTermInstrs.push_back(&MI);
479  break;
480 
481  default:
482  break;
483  }
484  }
485  }
486 
487  for (MachineInstr *Instr : EarlyTermInstrs) {
488  // Early termination in GS does nothing
489  if (MF.getFunction().getCallingConv() != CallingConv::AMDGPU_GS)
490  earlyTerm(*Instr);
491  Instr->eraseFromParent();
492  }
493  for (MachineInstr *Kill : KillInstrs) {
494  skipIfDead(*Kill->getParent(), std::next(Kill->getIterator()),
495  Kill->getDebugLoc());
496  Kill->eraseFromParent();
497  }
498  KillInstrs.clear();
499  EarlyTermInstrs.clear();
500  EarlyExitBlock = nullptr;
501 
502  return MadeChange;
503 }
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.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
char & SIInsertSkipsPassID
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
The last use of a register.
iterator_range< succ_iterator > successors()
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineBasicBlock & MBB
static void splitBlock(MachineBasicBlock &MBB, MachineInstr &MI, MachineDominatorTree *MDT)
Value of the register doesn't matter.
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
#define DEBUG_TYPE
static cl::opt< unsigned > SkipThresholdFlag("amdgpu-skip-threshold-legacy", cl::desc("Number of instructions before jumping over divergent control flow"), cl::init(12), cl::Hidden)
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
Core dominator tree base class.
Definition: LoopInfo.h:65
void applyUpdates(ArrayRef< UpdateType > Updates)
Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:427
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent the analysis usage information of a pass.
static unsigned SkipThreshold
MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
INITIALIZE_PASS_BEGIN(SIInsertSkips, DEBUG_TYPE, "SI insert s_cbranch_execz instructions", false, false) INITIALIZE_PASS_END(SIInsertSkips
self_iterator getIterator()
Definition: ilist_node.h:81
Calling convention used for Mesa/AMDPAL geometry shaders.
Definition: CallingConv.h:202
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Iterator for intrusive lists based on ilist_node.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
BlockVerifier::State From
LLVM_READONLY int getVOPe32(uint16_t Opcode)
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:228
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.
Definition: SmallVector.h:1116
Calling convention used for Mesa/AMDPAL pixel shaders.
Definition: CallingConv.h:205
LLVM_READONLY int getVCMPXNoSDstOp(uint16_t Opcode)
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
Representation of each machine instruction.
Definition: MachineInstr.h:62
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
#define I(x, y, z)
Definition: MD5.cpp:59
static bool opcodeEmitsNoInsts(const MachineInstr &MI)
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
aarch64 promote const
Register definition.
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
inst_range instructions(Function *F)
Definition: InstIterator.h:133
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static void generateEndPgm(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, const SIInstrInfo *TII, bool IsPS)
MachineBasicBlock MachineBasicBlock::iterator MBBI
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1563