LLVM: lib/Target/SPIRV/SPIRVStructurizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

24#include "llvm/IR/IntrinsicsSPIRV.h"

31#include

32#include <unordered_set>

33

34using namespace llvm;

35using namespace SPIRV;

36

37using BlockSet = std::unordered_set<BasicBlock *>;

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

39

40

41

45 V.partialOrderVisit(Start, std::move(Op));

46}

47

48

49

52 if (Node->Entry == BB)

54

55 for (auto *Child : Node->Children) {

57 if (CR != nullptr)

58 return CR;

59 }

60 return nullptr;

61}

62

63

64

66 std::unordered_set<BasicBlock *> ExitTargets;

71 }

72 }

73

74 assert(ExitTargets.size() <= 1);

75 if (ExitTargets.size() == 0)

76 return nullptr;

77

78 return *ExitTargets.begin();

79}

80

81

82

85 if (II == nullptr)

86 return nullptr;

87

88 if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&

89 II->getIntrinsicID() != Intrinsic::spv_selection_merge)

90 return nullptr;

91

94}

95

96

97

100 if (II == nullptr)

101 return nullptr;

102

103 if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)

104 return nullptr;

105

108}

109

110

111

113 for (auto &I : Header) {

115 if (MB == &Merge)

116 return true;

117 }

118 return false;

119}

120

121

123 for (auto &I : BB)

125 return true;

126 return false;

127}

128

129

130

134

135

136

143 }

144 }

145 return Output;

146}

147

148

149

155 if (MB != nullptr)

157 }

158 }

159 return Output;

160}

161

162

163

164

166 std::vector<Instruction *> Output;

169 Output.push_back(&I);

170 return Output;

171}

172

173

174

180 if (MB != nullptr)

182 }

183 }

184 return Output;

185}

186

187

188

190 std::stack<BasicBlock *> ToVisit;

192

193 ToVisit.push(&Start);

194 Seen.insert(ToVisit.top());

195 while (ToVisit.size() != 0) {

197 ToVisit.pop();

198

199 if (op(BB))

200 continue;

201

204 continue;

205 ToVisit.push(Succ);

207 }

208 }

209}

210

211

212

213

217

218

219 for (size_t i = 0; i < BI->getNumSuccessors(); i++) {

220 if (BI->getSuccessor(i) == OldTarget)

221 BI->setSuccessor(i, NewTarget);

222 }

223

224

225 if (BI->isUnconditional())

226 return;

227

228

229 if (BI->getSuccessor(0) != BI->getSuccessor(1))

230 return;

231

232

233

235 Builder.SetInsertPoint(BI);

236 Builder.CreateBr(BI->getSuccessor(0));

237 BI->eraseFromParent();

238

239

240 if (BB->size() == 1)

241 return;

242

243

244

245

248 if (II || II->getIntrinsicID() != Intrinsic::spv_selection_merge)

249 return;

250

252 II->eraseFromParent();

253 if (C->isConstantUsed())

254 C->destroyConstant();

255}

256

257

258

259

260

265 return;

266

269

271 for (size_t i = 0; i < SI->getNumSuccessors(); i++) {

272 if (SI->getSuccessor(i) == OldTarget)

273 SI->setSuccessor(i, NewTarget);

274 }

275 return;

276 }

277

278 assert(false && "Unhandled terminator type.");

279}

280

281namespace {

282

283

284class SPIRVStructurizer : public FunctionPass {

285 struct DivergentConstruct;

286

287

288

289 using ConstructList = std::vector<std::unique_ptr>;

290

291

292

293

294

295 struct DivergentConstruct {

299

300 DivergentConstruct *Parent = nullptr;

301 ConstructList Children;

302 };

303

304

305

306

307

308 struct Splitter {

310 LoopInfo &LI;

313

314 Splitter(Function &F, LoopInfo &LI) : F(F), LI(LI) { invalidate(); }

315

316 void invalidate() {

317 PDT.recalculate(F);

318 DT.recalculate(F);

319 }

320

321

322

323 std::vector<BasicBlock *> getLoopConstructBlocks(BasicBlock *Header,

324 BasicBlock *Merge) {

326 std::vector<BasicBlock *> Output;

329 return false;

330 if (DT.dominates(Merge, BB) || !DT.dominates(Header, BB))

331 return false;

332 Output.push_back(BB);

333 return true;

334 });

335 return Output;

336 }

337

338

339 std::vector<BasicBlock *>

340 getSelectionConstructBlocks(DivergentConstruct *Node) {

343 OutsideBlocks.insert(Node->Merge);

344

345 for (DivergentConstruct *It = Node->Parent; It != nullptr;

346 It = It->Parent) {

347 OutsideBlocks.insert(It->Merge);

348 if (It->Continue)

349 OutsideBlocks.insert(It->Continue);

350 }

351

352 std::vector<BasicBlock *> Output;

354 if (OutsideBlocks.count(BB) != 0)

355 return false;

356 if (DT.dominates(Node->Merge, BB) || !DT.dominates(Node->Header, BB))

357 return false;

358 Output.push_back(BB);

359 return true;

360 });

361 return Output;

362 }

363

364

365 std::vector<BasicBlock *> getSwitchConstructBlocks(BasicBlock *Header,

366 BasicBlock *Merge) {

368

369 std::vector<BasicBlock *> Output;

371

372 if (!DT.dominates(Header, BB))

373 return false;

374

375

376 if (DT.dominates(Merge, BB) || BB == Merge)

377 return false;

378 Output.push_back(BB);

379 return true;

380 });

381 return Output;

382 }

383

384

385 std::vector<BasicBlock *> getCaseConstructBlocks(BasicBlock *Target,

386 BasicBlock *Merge) {

388

389 std::vector<BasicBlock *> Output;

391

392

393 if (!DT.dominates(Target, BB))

394 return false;

395

396

397 if (DT.dominates(Merge, BB) || BB == Merge)

398 return false;

399 Output.push_back(BB);

400 return true;

401 });

402 return Output;

403 }

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427 std::vector

428 createAliasBlocksForComplexEdges(std::vector Edges) {

429 std::unordered_set<BasicBlock *> Seen;

430 std::vector Output;

431 Output.reserve(Edges.size());

432

433 for (auto &[Src, Dst] : Edges) {

434 auto [Iterator, Inserted] = Seen.insert(Src);

435 if (!Inserted) {

436

437

439 F.getContext(), Src->getName() + ".new.src", &F);

442 Builder.CreateBr(Dst);

443 Src = NewSrc;

444 }

445

446 Output.emplace_back(Src, Dst);

447 }

448

449 return Output;

450 }

451

452 AllocaInst *CreateVariable(Function &F, Type *Type,

454 const DataLayout &DL = F.getDataLayout();

455 return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",

456 Position);

457 }

458

459

460

461 BasicBlock *createSingleExitNode(BasicBlock *Header,

462 std::vector &Edges) {

463

464 std::vector FixedEdges = createAliasBlocksForComplexEdges(Edges);

465

466 std::vector<BasicBlock *> Dsts;

467 std::unordered_map<BasicBlock *, ConstantInt *> DstToIndex;

469 Header->getName() + ".new.exit", &F);

471 for (auto &[Src, Dst] : FixedEdges) {

472 if (DstToIndex.count(Dst) != 0)

473 continue;

474 DstToIndex.emplace(Dst, ExitBuilder.getInt32(DstToIndex.size()));

475 Dsts.push_back(Dst);

476 }

477

478 if (Dsts.size() == 1) {

479 for (auto &[Src, Dst] : FixedEdges) {

481 }

482 ExitBuilder.CreateBr(Dsts[0]);

483 return NewExit;

484 }

485

486 AllocaInst *Variable = CreateVariable(F, ExitBuilder.getInt32Ty(),

487 F.begin()->getFirstInsertionPt());

488 for (auto &[Src, Dst] : FixedEdges) {

490 B2.SetInsertPoint(Src->getFirstInsertionPt());

491 B2.CreateStore(DstToIndex[Dst], Variable);

493 }

494

495 Value *Load = ExitBuilder.CreateLoad(ExitBuilder.getInt32Ty(), Variable);

496

497

498

499

500 if (Dsts.size() == 2) {

501 Value *Condition =

502 ExitBuilder.CreateCmp(CmpInst::ICMP_EQ, DstToIndex[Dsts[0]], Load);

503 ExitBuilder.CreateCondBr(Condition, Dsts[0], Dsts[1]);

504 return NewExit;

505 }

506

507 SwitchInst *Sw = ExitBuilder.CreateSwitch(Load, Dsts[0], Dsts.size() - 1);

508 for (BasicBlock *BB : drop_begin(Dsts))

509 Sw->addCase(DstToIndex[BB], BB);

510 return NewExit;

511 }

512 };

513

514

515

516 Value *createExitVariable(

517 BasicBlock *BB,

518 const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {

521 return nullptr;

522

524 Builder.SetInsertPoint(T);

525

527

528 BasicBlock *LHSTarget = BI->getSuccessor(0);

530 BI->isConditional() ? BI->getSuccessor(1) : nullptr;

531

534

535 if (LHS == nullptr || RHS == nullptr)

536 return LHS == nullptr ? RHS : LHS;

537 return Builder.CreateSelect(BI->getCondition(), LHS, RHS);

538 }

539

540

542 }

543

544

545 BasicBlock *CreateUnreachable(Function &F) {

548 Builder.CreateUnreachable();

549 return BB;

550 }

551

552

553 bool addMergeForLoops(Function &F) {

554 LoopInfo &LI = getAnalysis().getLoopInfo();

555 auto *TopLevelRegion =

556 getAnalysis()

557 .getRegionInfo()

558 .getTopLevelRegion();

559

561 for (auto &BB : F) {

562

564 continue;

566

567

568

570 if (CR == nullptr)

571 continue;

572

574

576

577

578

579

580

581

582 if (Merge == nullptr) {

585

586 Merge = CreateUnreachable(F);

587 Builder.SetInsertPoint(Br);

588 Builder.CreateCondBr(Builder.getFalse(), Merge, Br->getSuccessor(0));

590 }

591

592 auto *Continue = L->getLoopLatch();

593

597 SmallVector<Value *, 2> Args = {MergeAddress, ContinueAddress};

600 for (unsigned Imm : LoopControlImms)

601 Args.emplace_back(ConstantInt::get(Builder.getInt32Ty(), Imm));

602 Builder.CreateIntrinsic(Intrinsic::spv_loop_merge, {Args});

604 }

605

607 }

608

609

610

611

612 bool addMergeForNodesWithMultiplePredecessors(Function &F) {

615

617 for (auto &BB : F) {

619 continue;

620

622 continue;

623

626

628 continue;

629

631 Builder.SetInsertPoint(Header->getTerminator());

632

634 createOpSelectMerge(&Builder, MergeAddress);

635

637 }

638

640 }

641

642

643

644

645

646

647 bool sortSelectionMerge(Function &F, BasicBlock &Block) {

648 std::vector<Instruction *> MergeInstructions;

649 for (Instruction &I : Block)

651 MergeInstructions.push_back(&I);

652

653 if (MergeInstructions.size() <= 1)

654 return false;

655

656 Instruction *InsertionPoint = *MergeInstructions.begin();

657

658 PartialOrderingVisitor Visitor(F);

659 std::sort(MergeInstructions.begin(), MergeInstructions.end(),

660 [&Visitor](Instruction *Left, Instruction *Right) {

661 if (Left == Right)

662 return false;

663 BasicBlock *RightMerge = getDesignatedMergeBlock(Right);

664 BasicBlock *LeftMerge = getDesignatedMergeBlock(Left);

665 return !Visitor.compare(RightMerge, LeftMerge);

666 });

667

668 for (Instruction *I : MergeInstructions) {

669 I->moveBefore(InsertionPoint->getIterator());

670 InsertionPoint = I;

671 }

672

673 return true;

674 }

675

676

677

678

679 bool sortSelectionMergeHeaders(Function &F) {

681 for (BasicBlock &BB : F) {

682 Modified |= sortSelectionMerge(F, BB);

683 }

685 }

686

687

688

689 bool splitBlocksWithMultipleHeaders(Function &F) {

690 std::stack<BasicBlock *> Work;

691 for (auto &BB : F) {

693 if (MergeInstructions.size() <= 1)

694 continue;

695 Work.push(&BB);

696 }

697

698 const bool Modified = Work.size() > 0;

699 while (Work.size() > 0) {

701 Work.pop();

702

703 std::vector<Instruction *> MergeInstructions =

705 for (unsigned i = 1; i < MergeInstructions.size(); i++) {

707 Header->splitBasicBlock(MergeInstructions[i], "new.header");

708

710 BasicBlock *Unreachable = CreateUnreachable(F);

711

714 Builder.SetInsertPoint(BI);

715 Builder.CreateCondBr(Builder.getTrue(), NewBlock, Unreachable);

717 }

718

719 Header = NewBlock;

720 }

721 }

722

724 }

725

726

727

728 bool addMergeForDivergentBlocks(Function &F) {

732

735

736 for (auto &BB : F) {

738 continue;

739

740 std::vector<BasicBlock *> Candidates;

742 if (MergeBlocks.contains(Successor))

743 continue;

744 if (ContinueBlocks.contains(Successor))

745 continue;

747 }

748

749 if (Candidates.size() <= 1)

750 continue;

751

754

758 createOpSelectMerge(&Builder, MergeAddress);

759 }

760

762 }

763

764

765

766 std::vector getExitsFrom(const BlockSet &Construct,

767 BasicBlock &Header) {

768 std::vector Output;

769 visit(Header, [&](BasicBlock *Item) {

770 if (Construct.count(Item) == 0)

771 return false;

772

774 if (Construct.count(Successor) == 0)

775 Output.emplace_back(Item, Successor);

776 }

777 return true;

778 });

779

780 return Output;

781 }

782

783

784

785 void constructDivergentConstruct(BlockSet &Visited, Splitter &S,

786 BasicBlock *BB, DivergentConstruct *Parent) {

787 if (Visited.count(BB) != 0)

788 return;

789 Visited.insert(BB);

790

792 if (MIS.size() == 0) {

794 constructDivergentConstruct(Visited, S, Successor, Parent);

795 return;

796 }

797

798 assert(MIS.size() == 1);

800

803

804 auto Output = std::make_unique();

805 Output->Header = BB;

806 Output->Merge = Merge;

808 Output->Parent = Parent;

809

810 constructDivergentConstruct(Visited, S, Merge, Parent);

812 constructDivergentConstruct(Visited, S, Continue, Output.get());

813

815 constructDivergentConstruct(Visited, S, Successor, Output.get());

816

817 if (Parent)

818 Parent->Children.emplace_back(std::move(Output));

819 }

820

821

822 BlockSet getConstructBlocks(Splitter &S, DivergentConstruct *Node) {

824

825 if (Node->Continue) {

826 auto LoopBlocks = S.getLoopConstructBlocks(Node->Header, Node->Merge);

827 return BlockSet(LoopBlocks.begin(), LoopBlocks.end());

828 }

829

830 auto SelectionBlocks = S.getSelectionConstructBlocks(Node);

831 return BlockSet(SelectionBlocks.begin(), SelectionBlocks.end());

832 }

833

834

835

836 bool fixupConstruct(Splitter &S, DivergentConstruct *Node) {

838 for (auto &Child : Node->Children)

839 Modified |= fixupConstruct(S, Child.get());

840

841

842

843 if (Node->Parent == nullptr)

845

846

847

848

849 if (Node->Parent->Header == nullptr)

851

852

855

856 BlockSet ConstructBlocks = getConstructBlocks(S, Node);

857 auto Edges = getExitsFrom(ConstructBlocks, *Node->Header);

858

859

860 if (Edges.size() < 1)

862

863 bool HasBadEdge = Node->Merge == Node->Parent->Merge ||

864 Node->Merge == Node->Parent->Continue;

865

866 for (auto &[Src, Dst] : Edges) {

867

868

869

870

871

872

873 if (Node->Merge == Dst)

874 continue;

875

876

877

878 if (Node->Continue == Dst)

879 continue;

880

881

882

883 HasBadEdge = true;

884 }

885

886 if (!HasBadEdge)

888

889

890 BasicBlock *NewExit = S.createSingleExitNode(Node->Header, Edges);

891

892

893

894

895

897 assert(MergeInstructions.size() == 1);

902 I->setOperand(0, MergeAddress);

903 }

904

905

906

909

910 Node->Merge = NewExit;

911

912 S.invalidate();

913 return true;

914 }

915

916 bool splitCriticalEdges(Function &F) {

917 LoopInfo &LI = getAnalysis().getLoopInfo();

918 Splitter S(F, LI);

919

920 DivergentConstruct Root;

922 constructDivergentConstruct(Visited, S, &*F.begin(), &Root);

923 return fixupConstruct(S, &Root);

924 }

925

926

927

928

929

930

931 bool simplifyBranches(Function &F) {

933

934 for (BasicBlock &BB : F) {

936 if (!SI)

937 continue;

938 if (SI->getNumCases() > 1)

939 continue;

940

943 Builder.SetInsertPoint(SI);

944

945 if (SI->getNumCases() == 0) {

946 Builder.CreateBr(SI->getDefaultDest());

947 } else {

948 Value *Condition =

950 SI->case_begin()->getCaseValue());

951 Builder.CreateCondBr(Condition, SI->case_begin()->getCaseSuccessor(),

952 SI->getDefaultDest());

953 }

954 SI->eraseFromParent();

955 }

956

958 }

959

960

961

962

963 bool splitSwitchCases(Function &F) {

965

966 for (BasicBlock &BB : F) {

968 if (!SI)

969 continue;

970

972 Seen.insert(SI->getDefaultDest());

973

974 auto It = SI->case_begin();

975 while (It != SI->case_end()) {

977 if (Seen.count(Target) == 0) {

978 Seen.insert(Target);

979 ++It;

980 continue;

981 }

982

987 Builder.CreateBr(Target);

988 SI->addCase(It->getCaseValue(), NewTarget);

989 It = SI->removeCase(It);

990 }

991 }

992

994 }

995

996

997

998 bool removeUselessBlocks(Function &F) {

999 std::vector<BasicBlock *> ToRemove;

1000

1003

1004 for (BasicBlock &BB : F) {

1005 if (BB.size() != 1)

1006 continue;

1007

1009 continue;

1010

1011 if (MergeBlocks.count(&BB) != 0 || ContinueBlocks.count(&BB) != 0)

1012 continue;

1013

1015 continue;

1016

1018 std::vector<BasicBlock *> Predecessors(predecessors(&BB).begin(),

1020 for (BasicBlock *Predecessor : Predecessors)

1023 }

1024

1025 for (BasicBlock *BB : ToRemove)

1027

1028 return ToRemove.size() != 0;

1029 }

1030

1031 bool addHeaderToRemainingDivergentDAG(Function &F) {

1033

1037

1042

1043 for (BasicBlock &BB : F) {

1044 if (HeaderBlocks.count(&BB) != 0)

1045 continue;

1047 continue;

1048

1049 size_t CandidateEdges = 0;

1051 if (MergeBlocks.count(Successor) != 0 ||

1052 ContinueBlocks.count(Successor) != 0)

1053 continue;

1054 if (HeaderBlocks.count(Successor) != 0)

1055 continue;

1056 CandidateEdges += 1;

1057 }

1058

1059 if (CandidateEdges <= 1)

1060 continue;

1061

1064

1065 bool HasBadBlock = false;

1066 visit(*Header, [&](const BasicBlock *Node) {

1068 return false;

1070 return false;

1071 if (Node == Header || Node == Merge)

1072 return true;

1073

1074 HasBadBlock |= MergeBlocks.count(Node) != 0 ||

1075 ContinueBlocks.count(Node) != 0 ||

1076 HeaderBlocks.count(Node) != 0;

1077 return !HasBadBlock;

1078 });

1079

1080 if (HasBadBlock)

1081 continue;

1082

1084

1085 if (Merge == nullptr) {

1088 Builder.SetInsertPoint(Header->getTerminator());

1089

1091 createOpSelectMerge(&Builder, MergeAddress);

1092 continue;

1093 }

1094

1097 SplitInstruction = SplitInstruction->getPrevNode();

1099 Merge->splitBasicBlockBefore(SplitInstruction, "new.merge");

1100

1102 Builder.SetInsertPoint(Header->getTerminator());

1103

1105 createOpSelectMerge(&Builder, MergeAddress);

1106 }

1107

1109 }

1110

1111public:

1112 static char ID;

1113

1114 SPIRVStructurizer() : FunctionPass(ID) {}

1115

1118

1119

1120

1121

1122 Modified |= splitSwitchCases(F);

1123

1124

1125

1126

1127 Modified |= simplifyBranches(F);

1128

1129

1130

1131 Modified |= addMergeForLoops(F);

1132

1133

1134 Modified |= addMergeForNodesWithMultiplePredecessors(F);

1135

1136

1137

1138

1139 Modified |= sortSelectionMergeHeaders(F);

1140

1141

1142

1143

1144 Modified |= splitBlocksWithMultipleHeaders(F);

1145

1146

1147

1148

1149

1150 Modified |= addMergeForDivergentBlocks(F);

1151

1152

1153

1154

1155

1156

1157

1158 Modified |= splitCriticalEdges(F);

1159

1160

1161

1162

1163

1164

1165

1166

1167

1168

1169 Modified |= removeUselessBlocks(F);

1170

1171

1172

1173

1174 Modified |= addHeaderToRemainingDivergentDAG(F);

1175

1176

1178

1180 }

1181

1182 void getAnalysisUsage(AnalysisUsage &AU) const override {

1183 AU.addRequired();

1185 AU.addRequired();

1186

1187 AU.addPreserved();

1188 FunctionPass::getAnalysisUsage(AU);

1189 }

1190

1191 void createOpSelectMerge(IRBuilder<> *Builder, BlockAddress *MergeAddress) {

1193

1194 MDNode *MDNode = BBTerminatorInst->getMetadata("hlsl.controlflow.hint");

1195

1196 ConstantInt *BranchHint = ConstantInt::get(Builder->getInt32Ty(), 0);

1197

1198 if (MDNode) {

1200 "invalid metadata hlsl.controlflow.hint");

1202 }

1203

1204 SmallVector<Value *, 2> Args = {MergeAddress, BranchHint};

1205

1206 Builder->CreateIntrinsic(Intrinsic::spv_selection_merge,

1208 }

1209};

1210}

1211

1212char SPIRVStructurizer::ID = 0;

1213

1215 "structurize SPIRV", false, false)

1220

1223

1225 return new SPIRVStructurizer();

1226}

1227

1230

1233

1234 if (!FPM.run(F))

1238 return PA;

1239}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

ReachingDefInfo InstSet & ToRemove

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file defines the DenseMap class.

static bool runOnFunction(Function &F, bool PostInlining)

This file provides various utilities for inspecting and working with the control flow graph in LLVM I...

uint64_t IntrinsicInst * II

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

static BasicBlock * getDesignatedMergeBlock(Instruction *I)

Definition SPIRVStructurizer.cpp:83

static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)

Definition SPIRVStructurizer.cpp:189

static std::vector< Instruction * > getMergeInstructions(BasicBlock &BB)

Definition SPIRVStructurizer.cpp:165

static BasicBlock * getDesignatedContinueBlock(Instruction *I)

Definition SPIRVStructurizer.cpp:98

std::unordered_set< BasicBlock * > BlockSet

Definition SPIRVStructurizer.cpp:37

static const ConvergenceRegion * getRegionForHeader(const ConvergenceRegion *Node, BasicBlock *BB)

Definition SPIRVStructurizer.cpp:51

static bool hasLoopMergeInstruction(BasicBlock &BB)

Definition SPIRVStructurizer.cpp:122

static SmallPtrSet< BasicBlock *, 2 > getContinueBlocks(Function &F)

Definition SPIRVStructurizer.cpp:175

static SmallPtrSet< BasicBlock *, 2 > getMergeBlocks(Function &F)

Definition SPIRVStructurizer.cpp:150

static SmallPtrSet< BasicBlock *, 2 > getHeaderBlocks(Function &F)

Definition SPIRVStructurizer.cpp:137

static bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge)

Definition SPIRVStructurizer.cpp:112

static void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget, BasicBlock *NewTarget)

Definition SPIRVStructurizer.cpp:261

static void partialOrderVisit(BasicBlock &Start, std::function< bool(BasicBlock *)> Op)

Definition SPIRVStructurizer.cpp:42

static bool isMergeInstruction(Instruction *I)

Definition SPIRVStructurizer.cpp:131

static BasicBlock * getExitFor(const ConvergenceRegion *CR)

Definition SPIRVStructurizer.cpp:65

static void replaceIfBranchTargets(BasicBlock *BB, BasicBlock *OldTarget, BasicBlock *NewTarget)

Definition SPIRVStructurizer.cpp:214

This file defines the SmallPtrSet class.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM Basic Block Representation.

const Function * getParent() const

Return the enclosing method, or null if none.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

LLVM_ABI const BasicBlock * getUniqueSuccessor() const

Return the successor of this block if it has a unique successor.

LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()

Unlink 'this' from the containing function and delete it.

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

The address of a basic block.

BasicBlock * getBasicBlock() const

static LLVM_ABI BlockAddress * get(Function *F, BasicBlock *BB)

Return a BlockAddress for the specified function and basic block.

BasicBlock * getSuccessor(unsigned i) const

bool isUnconditional() const

Represents analyses that only rely on functions' control flow.

This is an important base class in LLVM.

LLVM_ABI bool isConstantUsed() const

Return true if the constant has users other than constant expressions and other dangling things.

LLVM_ABI void destroyConstant()

Called if some element of this constant is no longer valid.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const

dominates - Returns true iff A dominates B.

void recalculate(ParentType &Func)

recalculate - compute a dominator tree for the given function

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.

FunctionPass class - This class is used to implement most global optimizations.

IntegerType * getInt32Ty()

Fetch the type representing a 32-bit integer.

BasicBlock * GetInsertBlock() const

LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

MDNode * getMetadata(unsigned KindID) const

Get the metadata of given kind attached to this Instruction.

A wrapper class for inspecting calls to intrinsic functions.

bool isLoopHeader(const BlockT *BB) const

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.

const MDOperand & getOperand(unsigned I) const

unsigned getNumOperands() const

Return number of MDNode operands.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

PreservedAnalyses run(Function &M, FunctionAnalysisManager &AM)

Definition SPIRVStructurizer.cpp:1228

SmallPtrSet< BasicBlock *, 2 > Exits

SmallPtrSet< BasicBlock *, 8 > Blocks

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

bool contains(ConstPtrType Ptr) const

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)

Add an entry to the switch instruction.

Type * getType() const

All values are typed, get the type of this value.

self_iterator getIterator()

FunctionPassManager manages FunctionPasses.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

@ C

The default llvm calling convention, compatible with C.

PostDomTreeBase< BasicBlock > BBPostDomTree

DomTreeBase< BasicBlock > BBDomTree

@ BasicBlock

Various leaf nodes.

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)

Extract a Value from Metadata.

NodeAddr< NodeBase * > Node

friend class Instruction

Iterator for Instructions in a `BasicBlock.

LLVM_ABI iterator begin() const

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

FunctionAddr VTableAddr Value

FunctionPass * createSPIRVStructurizerPass()

Definition SPIRVStructurizer.cpp:1224

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto successors(const MachineBasicBlock *BB)

bool sortBlocks(Function &F)

auto pred_size(const MachineBasicBlock *BB)

SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(Loop *L)

auto dyn_cast_or_null(const Y &Val)

auto succ_size(const MachineBasicBlock *BB)

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

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

auto predecessors(const MachineBasicBlock *BB)

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.