29 #define DEBUG_TYPE "si-annotate-control-flow"
34 typedef std::pair<BasicBlock *, Value *> StackEntry;
38 static const char *
const IfIntrinsic =
"llvm.amdgcn.if";
39 static const char *
const ElseIntrinsic =
"llvm.amdgcn.else";
40 static const char *
const BreakIntrinsic =
"llvm.amdgcn.break";
41 static const char *
const IfBreakIntrinsic =
"llvm.amdgcn.if.break";
42 static const char *
const ElseBreakIntrinsic =
"llvm.amdgcn.else.break";
43 static const char *
const LoopIntrinsic =
"llvm.amdgcn.loop";
44 static const char *
const EndCfIntrinsic =
"llvm.amdgcn.end.cf";
82 void eraseIfUnused(
PHINode *Phi);
98 SIAnnotateControlFlow():
101 bool doInitialization(
Module &M)
override;
103 bool runOnFunction(
Function &
F)
override;
105 StringRef getPassName()
const override {
return "SI annotate control flow"; }
120 "Annotate SI Control Flow",
false,
false)
123 "Annotate SI Control
Flow",
false, false)
125 char SIAnnotateControlFlow::
ID = 0;
128 bool SIAnnotateControlFlow::doInitialization(
Module &M) {
141 If = M.getOrInsertFunction(
142 IfIntrinsic, ReturnStruct,
Boolean, (
Type *)
nullptr);
144 Else = M.getOrInsertFunction(
145 ElseIntrinsic, ReturnStruct, Int64, (
Type *)
nullptr);
147 Break = M.getOrInsertFunction(
148 BreakIntrinsic, Int64, Int64, (
Type *)
nullptr);
151 IfBreak = M.getOrInsertFunction(
152 IfBreakIntrinsic, Int64,
Boolean, Int64, (
Type *)
nullptr);
155 ElseBreak = M.getOrInsertFunction(
156 ElseBreakIntrinsic, Int64, Int64, Int64, (
Type *)
nullptr);
159 Loop = M.getOrInsertFunction(
162 EndCf = M.getOrInsertFunction(
163 EndCfIntrinsic, Void, Int64, (
Type *)
nullptr);
170 bool SIAnnotateControlFlow::isUniform(
BranchInst *
T) {
172 T->
getMetadata(
"structurizecfg.uniform") !=
nullptr;
176 bool SIAnnotateControlFlow::isTopOfStack(
BasicBlock *BB) {
177 return !
Stack.empty() &&
Stack.back().first == BB;
181 Value *SIAnnotateControlFlow::popSaved() {
182 return Stack.pop_back_val().second;
187 Stack.push_back(std::make_pair(BB, Saved));
192 bool SIAnnotateControlFlow::isElse(
PHINode *Phi) {
210 void SIAnnotateControlFlow::eraseIfUnused(
PHINode *Phi) {
216 void SIAnnotateControlFlow::openIf(
BranchInst *Term) {
217 if (isUniform(Term)) {
226 void SIAnnotateControlFlow::insertElse(
BranchInst *Term) {
227 if (isUniform(Term)) {
245 if ((Phi = dyn_cast<PHINode>(Cond)) && L->
contains(Phi)) {
255 if (isa<ConstantInt>(Incoming)) {
261 Value *PhiArg = handleLoopCondition(Incoming, Broken, L, Term);
265 BasicBlock *IDom = DT->getNode(Parent)->getIDom()->getBlock();
270 if (Incoming != BoolTrue)
291 OldEnd = dyn_cast<CallInst>(OldEnd->
getNextNode());
305 }
else if (
Instruction *Inst = dyn_cast<Instruction>(Cond)) {
311 Insert = L->
getHeader()->getFirstNonPHIOrDbgOrLifetime();
317 }
else if (isa<ConstantInt>(Cond)) {
328 void SIAnnotateControlFlow::handleLoop(
BranchInst *Term) {
329 if (isUniform(Term)) {
342 Value *Arg = handleLoopCondition(Cond, Broken, L, Term);
347 Broken->
addIncoming(*PI == BB ? Arg : Int64Zero, *PI);
353 void SIAnnotateControlFlow::closeControlFlow(
BasicBlock *BB) {
365 std::vector<BasicBlock*> Preds;
368 Preds.push_back(*PI);
373 Value *Exec = popSaved();
374 if (!isa<UndefValue>(Exec))
380 bool SIAnnotateControlFlow::runOnFunction(
Function &
F) {
382 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
383 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
384 DA = &getAnalysis<DivergenceAnalysis>();
392 if (isTopOfStack(*
I))
393 closeControlFlow(*
I);
399 if (isTopOfStack(*
I))
400 closeControlFlow(*
I);
406 if (isTopOfStack(*
I)) {
408 if (Phi && Phi->
getParent() == *
I && isElse(Phi)) {
413 closeControlFlow(*
I);
424 return new SIAnnotateControlFlow();
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static ConstantInt * getFalse(LLVMContext &Context)
Annotate SI Control false
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static IntegerType * getInt1Ty(LLVMContext &C)
FunctionPass * createSIAnnotateControlFlowPass()
Create the annotation pass.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
void getLoopLatches(SmallVectorImpl< BlockT * > &LoopLatches) const
Return all loop latch blocks of this loop.
A Module instance is used to store all the information related to an LLVM module. ...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
This class represents a function call, abstracting a target machine's calling convention.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction & front() const
static IntegerType * getInt64Ty(LLVMContext &C)
BlockT * getHeader() const
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
bool isUnconditional() const
'undef' values are things that do not have specified contents.
BasicBlock * getSuccessor(unsigned i) const
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Subclasses of this class are all able to terminate a basic block.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
Conditional or Unconditional Branch instruction.
df_iterator< T > df_end(const T &G)
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
Interval::pred_iterator pred_end(Interval *I)
static bool setDoesNotAccessMemory(Function &F)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is the shared class of boolean and integer constants.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
const BasicBlock & getEntryBlock() const
static ConstantInt * getTrue(LLVMContext &Context)
df_iterator< T > df_begin(const T &G)
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
Target - Wrapper for Target specific information.
Maximum length of the test input If
Value * getCondition() const
Represents a single loop in the control flow graph.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasNUsesOrMore(unsigned N) const
Return true if this value has N users or more.
BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
void setCondition(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
The legacy pass manager's analysis pass to compute loop information.
StringRef - Represent a constant reference to a string, i.e.
Legacy analysis pass which computes a DominatorTree.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
void setIncomingValue(unsigned i, Value *V)
INITIALIZE_PASS_BEGIN(SIAnnotateControlFlow, DEBUG_TYPE,"Annotate SI Control Flow", false, false) INITIALIZE_PASS_END(SIAnnotateControlFlow
const BasicBlock * getParent() const
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.