23#include "llvm/IR/IntrinsicsAMDGPU.h"
31#define DEBUG_TYPE "si-annotate-control-flow"
36using StackEntry = std::pair<BasicBlock *, Value *>;
77 bool eraseIfUnused(
PHINode *Phi);
114 "Annotate SI Control Flow",
false,
false)
121char SIAnnotateControlFlow::
ID = 0;
136 IntMaskZero = ConstantInt::get(IntMask, 0);
140 { IntMask, IntMask });
149bool SIAnnotateControlFlow::isUniform(
BranchInst *
T) {
150 return UA->isUniform(
T) ||
T->hasMetadata(
"structurizecfg.uniform");
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) {
210 Value *IfCall = IRB.CreateCall(If, {
Term->getCondition()});
211 Value *
Cond = IRB.CreateExtractValue(IfCall, {0});
212 Value *
Mask = IRB.CreateExtractValue(IfCall, {1});
219bool SIAnnotateControlFlow::insertElse(
BranchInst *Term) {
220 if (isUniform(Term)) {
225 Value *ElseCall = IRB.CreateCall(Else, {popSaved()});
226 Value *
Cond = IRB.CreateExtractValue(ElseCall, {0});
227 Value *
Mask = IRB.CreateExtractValue(ElseCall, {1});
234Value *SIAnnotateControlFlow::handleLoopCondition(
244 if (
L->contains(Inst)) {
247 Insert =
L->getHeader()->getFirstNonPHIOrDbgOrLifetime();
250 return CreateBreak(Insert);
254 if (isa<Constant>(
Cond)) {
256 Term :
L->getHeader()->getTerminator();
258 return CreateBreak(Insert);
261 if (isa<Argument>(
Cond)) {
263 return CreateBreak(Insert);
270bool SIAnnotateControlFlow::handleLoop(
BranchInst *Term) {
284 Term->setCondition(BoolTrue);
285 Value *Arg = handleLoopCondition(
Cond, Broken, L, Term);
288 Value *PHIValue = IntMaskZero;
294 else if (
L->contains(Pred) && DT->dominates(Pred, BB))
300 Term->setCondition(LoopCall);
308bool SIAnnotateControlFlow::closeControlFlow(
BasicBlock *BB) {
313 if (L &&
L->getHeader() == BB) {
317 SmallVector <BasicBlock *, 8> Latches;
318 L->getLoopLatches(Latches);
332 if (!isa<UndefValue>(Exec) && !isa<UnreachableInst>(FirstInsertionPt)) {
335 if (!DT->dominates(DefBB, BB)) {
339 IRBuilder<>(FirstInsertionPt->getParent(), FirstInsertionPt)
348bool SIAnnotateControlFlow::runOnFunction(
Function &
F) {
349 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
350 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
351 UA = &getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
355 bool Changed =
false;
358 E =
df_end(&
F.getEntryBlock());
I != E; ++
I) {
362 if (!Term ||
Term->isUnconditional()) {
363 if (isTopOfStack(BB))
364 Changed |= closeControlFlow(BB);
369 if (
I.nodeVisited(
Term->getSuccessor(1))) {
370 if (isTopOfStack(BB))
371 Changed |= closeControlFlow(BB);
373 if (DT->dominates(
Term->getSuccessor(1), BB))
374 Changed |= handleLoop(Term);
378 if (isTopOfStack(BB)) {
380 if (Phi &&
Phi->getParent() == BB && isElse(Phi) && !hasKill(BB)) {
381 Changed |= insertElse(Term);
382 Changed |= eraseIfUnused(Phi);
386 Changed |= closeControlFlow(BB);
389 Changed |= openIf(Term);
392 if (!
Stack.empty()) {
402 return new SIAnnotateControlFlow();
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.
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 or Unconditional Branch instruction.
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
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.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
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, BasicBlock::iterator InsertBefore)
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 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.
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.