46 #define DEBUG_TYPE "si-annotate-control-flow" 51 using StackEntry = std::pair<BasicBlock *, Value *>;
88 void eraseIfUnused(
PHINode *Phi);
107 bool doInitialization(
Module &M)
override;
111 StringRef getPassName()
const override {
return "SI annotate control flow"; }
125 "Annotate SI Control Flow",
false,
false)
131 char SIAnnotateControlFlow::
ID = 0;
134 bool SIAnnotateControlFlow::doInitialization(
Module &M) {
157 bool SIAnnotateControlFlow::isUniform(
BranchInst *
T) {
158 return DA->isUniform(T) ||
159 T->
getMetadata(
"structurizecfg.uniform") !=
nullptr;
163 bool SIAnnotateControlFlow::isTopOfStack(
BasicBlock *BB) {
164 return !Stack.empty() && Stack.back().first == BB;
168 Value *SIAnnotateControlFlow::popSaved() {
169 return Stack.pop_back_val().second;
174 Stack.push_back(std::make_pair(BB, Saved));
179 bool SIAnnotateControlFlow::isElse(
PHINode *Phi) {
197 void SIAnnotateControlFlow::eraseIfUnused(
PHINode *Phi) {
204 void SIAnnotateControlFlow::openIf(
BranchInst *Term) {
214 void SIAnnotateControlFlow::insertElse(
BranchInst *Term) {
215 if (isUniform(Term)) {
224 Value *SIAnnotateControlFlow::handleLoopCondition(
226 if (
Instruction *Inst = dyn_cast<Instruction>(Cond)) {
240 if (isa<Constant>(Cond)) {
252 void SIAnnotateControlFlow::handleLoop(
BranchInst *Term) {
266 Value *
Arg = handleLoopCondition(Cond, Broken, L, Term);
269 Broken->
addIncoming(Pred == BB ? Arg : Int64Zero, Pred);
277 void SIAnnotateControlFlow::closeControlFlow(
BasicBlock *BB) {
280 assert(Stack.back().first == BB);
299 Value *Exec = popSaved();
301 if (!isa<UndefValue>(Exec) && !isa<UnreachableInst>(FirstInsertionPt))
308 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
309 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
310 DA = &getAnalysis<LegacyDivergenceAnalysis>();
318 if (isTopOfStack(BB))
319 closeControlFlow(BB);
325 if (isTopOfStack(BB))
326 closeControlFlow(BB);
332 if (isTopOfStack(BB)) {
334 if (Phi && Phi->
getParent() == BB && isElse(Phi)) {
340 closeControlFlow(BB);
346 if (!Stack.empty()) {
356 return new SIAnnotateControlFlow();
static ConstantInt * getFalse(LLVMContext &Context)
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.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module. ...
INITIALIZE_PASS_BEGIN(SIAnnotateControlFlow, DEBUG_TYPE, "Annotate SI Control Flow", false, false) INITIALIZE_PASS_END(SIAnnotateControlFlow
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
void push_back(const T &Elt)
BasicBlock * getSuccessor(unsigned i) const
static IntegerType * getInt64Ty(LLVMContext &C)
Value * getCondition() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
'undef' values are things that do not have specified contents.
void getLoopLatches(SmallVectorImpl< BlockT *> &LoopLatches) const
Return all loop latch blocks of this loop.
static StructType * get(LLVMContext &Context, ArrayRef< Type *> Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
BlockT * getHeader() const
const Instruction * getFirstNonPHIOrDbgOrLifetime() const
Returns a pointer to the first instruction in this block that is not a PHINode, a debug intrinsic...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type *> Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
const BasicBlock & getEntryBlock() const
static bool runOnFunction(Function &F, bool PostInlining)
BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock *> Preds, const char *Suffix, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
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)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const Instruction & front() const
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
FunctionPass class - This class is used to implement most global optimizations.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
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.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
This is the shared class of boolean and integer constants.
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.
bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=nullptr)
If the specified value is an effectively dead PHI node, due to being a def-use chain of single-use no...
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.
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...
pred_range predecessors(BasicBlock *BB)
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static ConstantInt * getTrue(LLVMContext &Context)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
df_iterator< T > df_begin(const T &G)
Target - Wrapper for Target specific information.
amdgpu Simplify well known AMD library false Value Value * Arg
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Represents a single loop in the control flow graph.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
const Function * getParent() const
Return the enclosing method, or null if none.
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 isUnconditional() const
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.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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.