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; assumes that the block is well-formed.
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...