22#include "llvm/IR/IntrinsicsAMDGPU.h"
30#define DEBUG_TYPE "si-annotate-control-flow"
35using StackEntry = std::pair<BasicBlock *, Value *>;
76 bool eraseIfUnused(
PHINode *Phi);
113 "Annotate SI Control Flow",
false,
false)
120char SIAnnotateControlFlow::
ID = 0;
139 { IntMask, IntMask });
148bool SIAnnotateControlFlow::isUniform(
BranchInst *
T) {
149 return UA->isUniform(
T) ||
150 T->getMetadata(
"structurizecfg.uniform") !=
nullptr;
154bool SIAnnotateControlFlow::isTopOfStack(
BasicBlock *BB) {
155 return !
Stack.empty() &&
Stack.back().first == BB;
159Value *SIAnnotateControlFlow::popSaved() {
160 return Stack.pop_back_val().second;
170bool SIAnnotateControlFlow::isElse(
PHINode *Phi) {
171 BasicBlock *IDom = DT->getNode(
Phi->getParent())->getIDom()->getBlock();
172 for (
unsigned i = 0, e =
Phi->getNumIncomingValues(); i != e; ++i) {
173 if (
Phi->getIncomingBlock(i) == IDom) {
175 if (
Phi->getIncomingValue(i) != BoolTrue)
179 if (
Phi->getIncomingValue(i) != BoolFalse)
187bool SIAnnotateControlFlow::hasKill(
const BasicBlock *BB) {
189 if (
const CallInst *CI = dyn_cast<CallInst>(&
I))
190 if (CI->getIntrinsicID() == Intrinsic::amdgcn_kill)
197bool SIAnnotateControlFlow::eraseIfUnused(
PHINode *Phi) {
205bool SIAnnotateControlFlow::openIf(
BranchInst *Term) {
216bool SIAnnotateControlFlow::insertElse(
BranchInst *Term) {
217 if (isUniform(Term)) {
227Value *SIAnnotateControlFlow::handleLoopCondition(
232 if (
L->contains(Inst)) {
235 Insert =
L->getHeader()->getFirstNonPHIOrDbgOrLifetime();
243 if (isa<Constant>(
Cond)) {
245 Term :
L->getHeader()->getTerminator();
251 if (isa<Argument>(
Cond)) {
261bool SIAnnotateControlFlow::handleLoop(
BranchInst *Term) {
275 Term->setCondition(BoolTrue);
276 Value *Arg = handleLoopCondition(
Cond, Broken, L, Term);
279 Value *PHIValue = IntMaskZero;
285 else if (
L->contains(Pred) && DT->dominates(Pred, BB))
298bool SIAnnotateControlFlow::closeControlFlow(
BasicBlock *BB) {
303 if (L &&
L->getHeader() == BB) {
307 SmallVector <BasicBlock *, 8> Latches;
308 L->getLoopLatches(Latches);
322 if (!isa<UndefValue>(Exec) && !isa<UnreachableInst>(FirstInsertionPt)) {
325 if (!DT->dominates(DefBB, BB)) {
337bool SIAnnotateControlFlow::runOnFunction(
Function &
F) {
338 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
339 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
340 UA = &getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
344 bool Changed =
false;
351 if (!Term ||
Term->isUnconditional()) {
352 if (isTopOfStack(BB))
353 Changed |= closeControlFlow(BB);
358 if (
I.nodeVisited(
Term->getSuccessor(1))) {
359 if (isTopOfStack(BB))
360 Changed |= closeControlFlow(BB);
362 if (DT->dominates(
Term->getSuccessor(1), BB))
363 Changed |= handleLoop(Term);
367 if (isTopOfStack(BB)) {
369 if (Phi &&
Phi->getParent() == BB && isElse(Phi) && !hasKill(BB)) {
370 Changed |= insertElse(Term);
371 Changed |= eraseIfUnused(Phi);
375 Changed |= closeControlFlow(BB);
378 Changed |= openIf(Term);
381 if (!
Stack.empty()) {
391 return new SIAnnotateControlFlow();
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Fixup Statepoint Caller Saved
AMD GCN specific subclass of TargetSubtarget.
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
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...
Conditional or Unconditional Branch instruction.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
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 ConstantInt * getFalse(LLVMContext &Context)
This is an important base class in LLVM.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const BasicBlock * getParent() const
This is an important class for using LLVM in a threaded context.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
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...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TMC & getTM() const
Get the right type of TargetMachine for this target.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt1Ty(LLVMContext &C)
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
'undef' values are things that do not have specified contents.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
NodeAddr< PhiNode * > Phi
This is an optimization pass for GlobalISel generic memory operations.
df_iterator< T > df_begin(const T &G)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, 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...
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
If the specified value is an effectively dead PHI node, due to being a def-use chain of single-use no...
df_iterator< T > df_end(const T &G)
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
FunctionPass * createSIAnnotateControlFlowPass()
Create the annotation pass.