25#include "llvm/IR/IntrinsicsAMDGPU.h"
33#define DEBUG_TYPE "si-annotate-control-flow"
38using StackEntry = std::pair<BasicBlock *, Value *>;
41class SIAnnotateControlFlow {
81 bool eraseIfUnused(
PHINode *Phi);
103 :
F(&
F), UA(&UA), DT(&DT), LI(&LI) {
113void SIAnnotateControlFlow::initialize(
const GCNSubtarget &ST) {
114 LLVMContext &
Context =
F->getContext();
116 Void = Type::getVoidTy(
Context);
118 IntMask =
ST.isWave32() ? Type::getInt32Ty(
Context)
125 IntMaskZero = ConstantInt::get(IntMask, 0);
130bool SIAnnotateControlFlow::isUniform(CondBrInst *
T) {
131 return UA->
isUniform(
T) ||
T->hasMetadata(
"structurizecfg.uniform");
135bool SIAnnotateControlFlow::isTopOfStack(BasicBlock *BB) {
136 return !Stack.empty() && Stack.back().first == BB;
140Value *SIAnnotateControlFlow::popSaved() {
141 return Stack.pop_back_val().second;
145void SIAnnotateControlFlow::push(BasicBlock *BB,
Value *
Saved) {
146 Stack.push_back(std::pair(BB,
Saved));
151bool SIAnnotateControlFlow::isElse(PHINode *Phi) {
153 for (
unsigned i = 0, e =
Phi->getNumIncomingValues(); i != e; ++i) {
154 if (
Phi->getIncomingBlock(i) == IDom) {
156 if (
Phi->getIncomingValue(i) != BoolTrue)
160 if (
Phi->getIncomingValue(i) != BoolFalse)
168bool SIAnnotateControlFlow::hasKill(
const BasicBlock *BB) {
169 for (
const Instruction &
I : *BB) {
171 if (CI->getIntrinsicID() == Intrinsic::amdgcn_kill)
178bool SIAnnotateControlFlow::eraseIfUnused(PHINode *Phi) {
186bool SIAnnotateControlFlow::openIf(CondBrInst *Term) {
191 Value *IfCall = IRB.CreateCall(getDecl(If, Intrinsic::amdgcn_if, IntMask),
192 {
Term->getCondition()});
193 Value *
Cond = IRB.CreateExtractValue(IfCall, {0});
194 Value *
Mask = IRB.CreateExtractValue(IfCall, {1});
196 push(
Term->getSuccessor(1), Mask);
201bool SIAnnotateControlFlow::insertElse(CondBrInst *Term) {
202 if (isUniform(Term)) {
207 Value *ElseCall = IRB.CreateCall(
208 getDecl(Else, Intrinsic::amdgcn_else, {IntMask, IntMask}), {popSaved()});
209 Value *
Cond = IRB.CreateExtractValue(ElseCall, {0});
210 Value *
Mask = IRB.CreateExtractValue(ElseCall, {1});
212 push(
Term->getSuccessor(1), Mask);
217Value *SIAnnotateControlFlow::handleLoopCondition(
Value *
Cond, PHINode *Broken,
223 getDecl(IfBreak, Intrinsic::amdgcn_if_break, IntMask), {
Cond, Broken});
234 }
else if (
L->contains(Inst)) {
237 Insert = &*
L->getHeader()->getFirstNonPHIOrDbgOrLifetime();
240 return CreateBreak(Insert);
246 Term :
L->getHeader()->getTerminator();
248 return CreateBreak(Insert);
253 return CreateBreak(Insert);
260bool SIAnnotateControlFlow::handleLoop(CondBrInst *Term) {
274 Term->setCondition(BoolTrue);
275 Value *Arg = handleLoopCondition(
Cond, Broken, L, Term);
278 Value *PHIValue = IntMaskZero;
284 else if (
L->contains(Pred) && DT->
dominates(Pred, BB))
290 getDecl(Loop, Intrinsic::amdgcn_loop, IntMask), {Arg});
291 Term->setCondition(LoopCall);
293 push(
Term->getSuccessor(0), Arg);
299bool SIAnnotateControlFlow::closeControlFlow(BasicBlock *BB) {
302 assert(Stack.back().first == BB);
304 if (L &&
L->getHeader() == BB) {
308 SmallVector <BasicBlock *, 8> Latches;
309 L->getLoopLatches(Latches);
330 IRBuilder<> IRB(FirstInsertionPt->getParent(), FirstInsertionPt);
334 IRB.SetCurrentDebugLocation(
DebugLoc());
335 IRB.CreateCall(getDecl(EndCf, Intrinsic::amdgcn_end_cf, IntMask), {
Exec});
343bool SIAnnotateControlFlow::run() {
346 for (df_iterator<BasicBlock *>
I =
df_begin(&
F->getEntryBlock()),
353 if (isTopOfStack(BB))
354 Changed |= closeControlFlow(BB);
359 if (
I.nodeVisited(
Term->getSuccessor(1))) {
360 if (isTopOfStack(BB))
361 Changed |= closeControlFlow(BB);
368 if (isTopOfStack(BB)) {
370 if (Phi &&
Phi->getParent() == BB && isElse(Phi) && !hasKill(BB)) {
376 Changed |= closeControlFlow(BB);
382 if (!Stack.empty()) {
398 SIAnnotateControlFlow Impl(
F, ST, DT, LI, UI);
437 SIAnnotateControlFlow Impl(
F, ST, DT, LI, UI);
443 "Annotate SI Control Flow",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
The AMDGPU TargetMachine interface definition for hw codegen targets.
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.
FunctionAnalysisManager FAM
#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
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
Target-Independent Code Generator Pass Configuration Options pass.
bool runOnFunction(Function &F) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
SIAnnotateControlFlowLegacy()
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
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 Branch instruction.
This is the shared class of boolean and integer constants.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
This is an important base class in LLVM.
DomTreeNodeBase * getIDom() const
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FunctionPass class - This class is used to implement most global optimizations.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
Analysis pass that exposes the LoopInfo for a function.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
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="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
In order to facilitate speculative execution, many instructions do not invoke immediate undefined beh...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
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 LLVM_ABI 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.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Target-Independent Code Generator Pass Configuration Options.
TMC & getTM() const
Get the right type of TargetMachine for this target.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
FunctionAddr VTableAddr Value
FunctionPass * createSIAnnotateControlFlowLegacyPass()
Create the annotation pass.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
df_iterator< T > df_begin(const T &G)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI 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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI 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)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI 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...