LLVM: lib/Target/AMDGPU/SIAnnotateControlFlow.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25#include "llvm/IR/IntrinsicsAMDGPU.h"

30

31using namespace llvm;

32

33#define DEBUG_TYPE "si-annotate-control-flow"

34

35namespace {

36

37

38using StackEntry = std::pair<BasicBlock *, Value *>;

40

41class SIAnnotateControlFlow {

42private:

45

48 Type *IntMask;

49 Type *ReturnStruct;

50

55

61

63 StackVector Stack;

64

66

68

70

72

73 Value *popSaved();

74

76

77 bool isElse(PHINode *Phi);

78

80

81 bool eraseIfUnused(PHINode *Phi);

82

84

86

90

92

93 bool closeControlFlow(BasicBlock *BB);

94

96 if (!Cache)

98 return Cache;

99 }

100

101public:

104 : F(&F), UA(&UA), DT(&DT), LI(&LI) {

106 }

107

108 bool run();

109};

110

111}

112

113

114void SIAnnotateControlFlow::initialize(const GCNSubtarget &ST) {

115 LLVMContext &Context = F->getContext();

116

117 Void = Type::getVoidTy(Context);

119 IntMask = ST.isWave32() ? Type::getInt32Ty(Context)

122

126 IntMaskZero = ConstantInt::get(IntMask, 0);

127}

128

129

130

131bool SIAnnotateControlFlow::isUniform(BranchInst *T) {

132 return UA->isUniform(T) || T->hasMetadata("structurizecfg.uniform");

133}

134

135

136bool SIAnnotateControlFlow::isTopOfStack(BasicBlock *BB) {

137 return !Stack.empty() && Stack.back().first == BB;

138}

139

140

141Value *SIAnnotateControlFlow::popSaved() {

142 return Stack.pop_back_val().second;

143}

144

145

146void SIAnnotateControlFlow::push(BasicBlock *BB, Value *Saved) {

147 Stack.push_back(std::pair(BB, Saved));

148}

149

150

151

152bool SIAnnotateControlFlow::isElse(PHINode *Phi) {

154 for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) {

155 if (Phi->getIncomingBlock(i) == IDom) {

156

157 if (Phi->getIncomingValue(i) != BoolTrue)

158 return false;

159

160 } else {

161 if (Phi->getIncomingValue(i) != BoolFalse)

162 return false;

163

164 }

165 }

166 return true;

167}

168

169bool SIAnnotateControlFlow::hasKill(const BasicBlock *BB) {

170 for (const Instruction &I : *BB) {

172 if (CI->getIntrinsicID() == Intrinsic::amdgcn_kill)

173 return true;

174 }

175 return false;

176}

177

178

179bool SIAnnotateControlFlow::eraseIfUnused(PHINode *Phi) {

182 LLVM_DEBUG(dbgs() << "Erased unused condition phi\n");

184}

185

186

187bool SIAnnotateControlFlow::openIf(BranchInst *Term) {

188 if (isUniform(Term))

189 return false;

190

192 Value *IfCall = IRB.CreateCall(getDecl(If, Intrinsic::amdgcn_if, IntMask),

193 {Term->getCondition()});

194 Value *Cond = IRB.CreateExtractValue(IfCall, {0});

195 Value *Mask = IRB.CreateExtractValue(IfCall, {1});

197 push(Term->getSuccessor(1), Mask);

198 return true;

199}

200

201

202bool SIAnnotateControlFlow::insertElse(BranchInst *Term) {

203 if (isUniform(Term)) {

204 return false;

205 }

206

208 Value *ElseCall = IRB.CreateCall(

209 getDecl(Else, Intrinsic::amdgcn_else, {IntMask, IntMask}), {popSaved()});

210 Value *Cond = IRB.CreateExtractValue(ElseCall, {0});

211 Value *Mask = IRB.CreateExtractValue(ElseCall, {1});

213 push(Term->getSuccessor(1), Mask);

214 return true;

215}

216

217

218Value *SIAnnotateControlFlow::handleLoopCondition(

219 Value *Cond, PHINode *Broken, llvm::Loop *L, BranchInst *Term) {

220

221 auto CreateBreak = [this, Cond, Broken](Instruction *I) -> CallInst * {

223 getDecl(IfBreak, Intrinsic::amdgcn_if_break, IntMask), {Cond, Broken});

224 };

225

227 BasicBlock *Parent = Inst->getParent();

230

231

232

234 } else if (L->contains(Inst)) {

236 } else {

237 Insert = &*L->getHeader()->getFirstNonPHIOrDbgOrLifetime();

238 }

239

240 return CreateBreak(Insert);

241 }

242

243

246 Term : L->getHeader()->getTerminator();

247

248 return CreateBreak(Insert);

249 }

250

252 Instruction *Insert = &*L->getHeader()->getFirstNonPHIOrDbgOrLifetime();

253 return CreateBreak(Insert);

254 }

255

257}

258

259

260bool SIAnnotateControlFlow::handleLoop(BranchInst *Term) {

261 if (isUniform(Term))

262 return false;

263

266 if (!L)

267 return false;

268

270 PHINode *Broken = PHINode::Create(IntMask, 0, "phi.broken");

272

274 Term->setCondition(BoolTrue);

275 Value *Arg = handleLoopCondition(Cond, Broken, L, Term);

276

277 for (BasicBlock *Pred : predecessors(Target)) {

278 Value *PHIValue = IntMaskZero;

279 if (Pred == BB)

280 PHIValue = Arg;

281

282

283

284 else if (L->contains(Pred) && DT->dominates(Pred, BB))

285 PHIValue = Broken;

287 }

288

289 CallInst *LoopCall = IRBuilder<>(Term).CreateCall(

290 getDecl(Loop, Intrinsic::amdgcn_loop, IntMask), {Arg});

291 Term->setCondition(LoopCall);

292

293 push(Term->getSuccessor(0), Arg);

294

295 return true;

296}

297

298

299bool SIAnnotateControlFlow::closeControlFlow(BasicBlock *BB) {

301

302 assert(Stack.back().first == BB);

303

304 if (L && L->getHeader() == BB) {

305

306

307

308 SmallVector <BasicBlock *, 8> Latches;

309 L->getLoopLatches(Latches);

310

315 }

316

318 false);

319 }

320

327

329 }

330 IRBuilder<> IRB(FirstInsertionPt->getParent(), FirstInsertionPt);

331

332

333

334 IRB.SetCurrentDebugLocation(DebugLoc());

335 IRB.CreateCall(getDecl(EndCf, Intrinsic::amdgcn_end_cf, IntMask), {Exec});

336 }

337

338 return true;

339}

340

341

342

343bool SIAnnotateControlFlow::run() {

345

346 for (df_iterator<BasicBlock *> I = df_begin(&F->getEntryBlock()),

347 E = df_end(&F->getEntryBlock());

348 I != E; ++I) {

351

352 if (!Term || Term->isUnconditional()) {

353 if (isTopOfStack(BB))

354 Changed |= closeControlFlow(BB);

355

356 continue;

357 }

358

359 if (I.nodeVisited(Term->getSuccessor(1))) {

360 if (isTopOfStack(BB))

361 Changed |= closeControlFlow(BB);

362

364 Changed |= handleLoop(Term);

365 continue;

366 }

367

368 if (isTopOfStack(BB)) {

370 if (Phi && Phi->getParent() == BB && isElse(Phi) && !hasKill(BB)) {

371 Changed |= insertElse(Term);

372 Changed |= eraseIfUnused(Phi);

373 continue;

374 }

375

376 Changed |= closeControlFlow(BB);

377 }

378

380 }

381

382 if (!Stack.empty()) {

383

385 }

386

388}

389

393

397

398 SIAnnotateControlFlow Impl(F, ST, DT, LI, UI);

399

400 bool Changed = Impl.run();

403

404

407 return PA;

408}

409

411public:

413

415

417

427

436

437 SIAnnotateControlFlow Impl(F, ST, DT, LI, UI);

438 return Impl.run();

439 }

440};

441

443 "Annotate SI Control Flow", false, false)

449

451

452

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.

LLVM IR instance of the generic uniformity analysis.

bool runOnFunction(Function &F) override

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.

Definition SIAnnotateControlFlow.cpp:428

SIAnnotateControlFlowLegacy()

Definition SIAnnotateControlFlow.cpp:414

StringRef getPassName() const override

getPassName - Return a nice clean name for a pass.

Definition SIAnnotateControlFlow.cpp:416

static char ID

Definition SIAnnotateControlFlow.cpp:412

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

Definition SIAnnotateControlFlow.cpp:418

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 or Unconditional 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.

bool isUniform(ConstValueRefT V) const

Whether V is uniform/non-divergent.

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() - 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)

Definition SIAnnotateControlFlow.cpp:390

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.

Analysis pass which computes UniformityInfo.

Legacy analysis pass which computes a CycleInfo.

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.

Definition SIAnnotateControlFlow.cpp:453

decltype(auto) dyn_cast(const From &Val)

dyn_cast - 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 - 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 - 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...