LLVM 24.0.0git
SPIRVStructurizer.cpp
Go to the documentation of this file.
1//===-- SPIRVStructurizer.cpp ----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//===----------------------------------------------------------------------===//
10
12#include "SPIRV.h"
14#include "SPIRVSubtarget.h"
15#include "SPIRVUtils.h"
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
20#include "llvm/IR/CFG.h"
21#include "llvm/IR/Dominators.h"
22#include "llvm/IR/IRBuilder.h"
24#include "llvm/IR/Intrinsics.h"
25#include "llvm/IR/IntrinsicsSPIRV.h"
31#include <optional>
32#include <stack>
33
34using namespace llvm;
35using namespace SPIRV;
36
38using Edge = std::pair<BasicBlock *, BasicBlock *>;
39
40// Returns the exact convergence region in the tree defined by `Node` for which
41// `BB` is the header, nullptr otherwise.
42static const ConvergenceRegion *
44 if (Node->Entry == BB)
45 return Node;
46
47 for (auto *Child : Node->Children) {
48 const auto *CR = getRegionForHeader(Child, BB);
49 if (CR != nullptr)
50 return CR;
51 }
52 return nullptr;
53}
54
55// Returns the single BasicBlock exiting the convergence region `CR`,
56// nullptr if no such exit exists.
59 for (BasicBlock *Exit : CR->Exits) {
60 for (BasicBlock *Successor : successors(Exit)) {
61 if (CR->Blocks.count(Successor) == 0)
62 ExitTargets.insert(Successor);
63 }
64 }
65
66 assert(ExitTargets.size() <= 1);
67 if (ExitTargets.size() == 0)
68 return nullptr;
69
70 return *ExitTargets.begin();
71}
72
73// Returns the merge block designated by I if I is a merge instruction, nullptr
74// otherwise.
77 if (II == nullptr)
78 return nullptr;
79
80 if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
81 II->getIntrinsicID() != Intrinsic::spv_selection_merge)
82 return nullptr;
83
84 BlockAddress *BA = cast<BlockAddress>(II->getOperand(0));
85 return BA->getBasicBlock();
86}
87
88// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
89// otherwise.
92 if (II == nullptr)
93 return nullptr;
94
95 if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
96 return nullptr;
97
98 BlockAddress *BA = cast<BlockAddress>(II->getOperand(1));
99 return BA->getBasicBlock();
100}
101
102// Returns true if Header has one merge instruction which designated Merge as
103// merge block.
105 for (auto &I : Header) {
107 if (MB == &Merge)
108 return true;
109 }
110 return false;
111}
112
113// Returns true if the BB has one OpLoopMerge instruction.
115 for (auto &I : BB)
117 return true;
118 return false;
119}
120
121// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
122// otherwise.
124 return getDesignatedMergeBlock(I) != nullptr;
125}
126
127// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
128// instruction.
131 for (BasicBlock &BB : F) {
132 for (Instruction &I : BB) {
133 if (getDesignatedMergeBlock(&I) != nullptr)
134 Output.insert(&BB);
135 }
136 }
137 return Output;
138}
139
140// Returns all basic blocks in |F| referenced by at least 1
141// OpSelectionMerge/OpLoopMerge instruction.
144 for (BasicBlock &BB : F) {
145 for (Instruction &I : BB) {
147 if (MB != nullptr)
148 Output.insert(MB);
149 }
150 }
151 return Output;
152}
153
154// Return all the merge instructions contained in BB.
155// Note: the SPIR-V spec doesn't allow a single BB to contain more than 1 merge
156// instruction, but this can happen while we structurize the CFG.
157static std::vector<Instruction *> getMergeInstructions(BasicBlock &BB) {
158 std::vector<Instruction *> Output;
159 for (Instruction &I : BB)
160 if (isMergeInstruction(&I))
161 Output.push_back(&I);
162 return Output;
163}
164
165// Returns all basic blocks in |F| referenced as continue target by at least 1
166// OpLoopMerge instruction.
169 for (BasicBlock &BB : F) {
170 for (Instruction &I : BB) {
172 if (MB != nullptr)
173 Output.insert(MB);
174 }
175 }
176 return Output;
177}
178
179// Do a preorder traversal of the CFG starting from the BB |Start|.
180// point. Calls |op| on each basic block encountered during the traversal.
181static void visit(BasicBlock &Start, std::function<bool(BasicBlock *)> op) {
182 std::stack<BasicBlock *> ToVisit;
184
185 ToVisit.push(&Start);
186 Seen.insert(ToVisit.top());
187 while (ToVisit.size() != 0) {
188 BasicBlock *BB = ToVisit.top();
189 ToVisit.pop();
190
191 if (!op(BB))
192 continue;
193
194 for (auto Succ : successors(BB)) {
195 if (Seen.contains(Succ))
196 continue;
197 ToVisit.push(Succ);
198 Seen.insert(Succ);
199 }
200 }
201}
202
203// Replaces the conditional and unconditional branch targets of |BB| by
204// |NewTarget| if the target was |OldTarget|. This function also makes sure the
205// associated merge instruction gets updated accordingly.
206static void replaceIfBranchTargets(BasicBlock *BB, BasicBlock *OldTarget,
207 BasicBlock *NewTarget) {
208 auto *BI = cast<CondBrInst>(BB->getTerminator());
209
210 // 1. Replace all matching successors.
211 for (size_t i = 0; i < BI->getNumSuccessors(); i++) {
212 if (BI->getSuccessor(i) == OldTarget)
213 BI->setSuccessor(i, NewTarget);
214 }
215
216 // Branch had 2 successors, maybe now both are the same?
217 if (BI->getSuccessor(0) != BI->getSuccessor(1))
218 return;
219
220 // Note: we may end up here because the original IR had such branches.
221 // This means Target is not necessarily equal to NewTarget.
222 IRBuilder<> Builder(BB);
223 Builder.SetInsertPoint(BI);
224 Builder.CreateBr(BI->getSuccessor(0));
225 BI->eraseFromParent();
226
227 // The branch was the only instruction, nothing else to do.
228 if (BB->size() == 1)
229 return;
230
231 // Otherwise, we need to check: was there an OpSelectionMerge before this
232 // branch? If we removed the OpBranchConditional, we must also remove the
233 // OpSelectionMerge. This is not valid for OpLoopMerge:
236 if (!II || II->getIntrinsicID() != Intrinsic::spv_selection_merge)
237 return;
238
239 Constant *C = cast<Constant>(II->getOperand(0));
240 II->eraseFromParent();
241 if (!C->isConstantUsed())
242 C->destroyConstant();
243}
244
245// Replaces the target of branch instruction in |BB| with |NewTarget| if it
246// was |OldTarget|. This function also fixes the associated merge instruction.
247// Note: this function does not simplify branching instructions, it only updates
248// targets. See also: simplifyBranches.
249static void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget,
250 BasicBlock *NewTarget) {
251 auto *T = BB->getTerminator();
252 if (isa<ReturnInst>(T))
253 return;
254 if (auto *BI = dyn_cast<UncondBrInst>(T)) {
255 if (BI->getSuccessor() == OldTarget)
256 BI->setSuccessor(NewTarget);
257 return;
258 }
259
260 if (isa<CondBrInst>(T))
261 return replaceIfBranchTargets(BB, OldTarget, NewTarget);
262
263 if (auto *SI = dyn_cast<SwitchInst>(T)) {
264 for (size_t i = 0; i < SI->getNumSuccessors(); i++) {
265 if (SI->getSuccessor(i) == OldTarget)
266 SI->setSuccessor(i, NewTarget);
267 }
268 return;
269 }
270
271 assert(false && "Unhandled terminator type.");
272}
273
274namespace {
275// Given a reducible CFG, produces a structurized CFG in the SPIR-V sense,
276// adding merge instructions when required.
277class SPIRVStructurizerImpl {
278 LoopInfo &LI;
279 ConvergenceRegionInfo &RegionInfo;
280
281 struct DivergentConstruct;
282 // Represents a list of condition/loops/switch constructs.
283 // See SPIR-V 2.11.2. Structured Control-flow Constructs for the list of
284 // constructs.
285 using ConstructList = std::vector<std::unique_ptr<DivergentConstruct>>;
286
287 // Represents a divergent construct in the SPIR-V sense.
288 // Such constructs are represented by a header (entry), a merge block (exit),
289 // and possibly a continue block (back-edge). A construct can contain other
290 // constructs, but their boundaries do not cross.
291 struct DivergentConstruct {
292 BasicBlock *Header = nullptr;
293 BasicBlock *Merge = nullptr;
294 BasicBlock *Continue = nullptr;
295
296 DivergentConstruct *Parent = nullptr;
297 ConstructList Children;
298 };
299
300 // An helper class to clean the construct boundaries.
301 // It is used to gather the list of blocks that should belong to each
302 // divergent construct, and possibly modify CFG edges when exits would cross
303 // the boundary of multiple constructs.
304 struct Splitter {
305 Function &F;
308 std::optional<PartialOrderingVisitor> POV;
309
310 Splitter(Function &F) : F(F) { invalidate(); }
311
312 void invalidate() {
313 PDT.recalculate(F);
314 POV.emplace(F);
315 }
316
317 const DomTreeBuilder::BBDomTree &getDT() const {
318 return POV->getDominatorTree();
319 }
320
321 // Returns the list of blocks that belong to a SPIR-V loop construct,
322 // including the continue construct.
323 std::vector<BasicBlock *> getLoopConstructBlocks(BasicBlock *Header,
324 BasicBlock *Merge) {
325 const DomTreeBuilder::BBDomTree &DT = getDT();
326 assert(DT.dominates(Header, Merge));
327 std::vector<BasicBlock *> Output;
328 POV->partialOrderVisit(*Header, [&](BasicBlock *BB) {
329 if (BB == Merge)
330 return false;
331 if (DT.dominates(Merge, BB) || !DT.dominates(Header, BB))
332 return false;
333 Output.push_back(BB);
334 return true;
335 });
336 return Output;
337 }
338
339 // Returns the list of blocks that belong to a SPIR-V selection construct.
340 std::vector<BasicBlock *>
341 getSelectionConstructBlocks(DivergentConstruct *Node) {
342 const DomTreeBuilder::BBDomTree &DT = getDT();
343 assert(DT.dominates(Node->Header, Node->Merge));
344 BlockSet OutsideBlocks;
345 OutsideBlocks.insert(Node->Merge);
346
347 for (DivergentConstruct *It = Node->Parent; It != nullptr;
348 It = It->Parent) {
349 OutsideBlocks.insert(It->Merge);
350 if (It->Continue)
351 OutsideBlocks.insert(It->Continue);
352 }
353
354 std::vector<BasicBlock *> Output;
355 POV->partialOrderVisit(*Node->Header, [&](BasicBlock *BB) {
356 if (OutsideBlocks.count(BB) != 0)
357 return false;
358 if (DT.dominates(Node->Merge, BB) || !DT.dominates(Node->Header, BB))
359 return false;
360 Output.push_back(BB);
361 return true;
362 });
363 return Output;
364 }
365
366 // Returns the list of blocks that belong to a SPIR-V switch construct.
367 std::vector<BasicBlock *> getSwitchConstructBlocks(BasicBlock *Header,
368 BasicBlock *Merge) {
369 const DomTreeBuilder::BBDomTree &DT = getDT();
370 assert(DT.dominates(Header, Merge));
371
372 std::vector<BasicBlock *> Output;
373 POV->partialOrderVisit(*Header, [&](BasicBlock *BB) {
374 // the blocks structurally dominated by a switch header,
375 if (!DT.dominates(Header, BB))
376 return false;
377 // excluding blocks structurally dominated by the switch header’s merge
378 // block.
379 if (DT.dominates(Merge, BB) || BB == Merge)
380 return false;
381 Output.push_back(BB);
382 return true;
383 });
384 return Output;
385 }
386
387 // Returns the list of blocks that belong to a SPIR-V case construct.
388 std::vector<BasicBlock *> getCaseConstructBlocks(BasicBlock *Target,
389 BasicBlock *Merge) {
390 const DomTreeBuilder::BBDomTree &DT = getDT();
391 assert(DT.dominates(Target, Merge));
392
393 std::vector<BasicBlock *> Output;
394 POV->partialOrderVisit(*Target, [&](BasicBlock *BB) {
395 // the blocks structurally dominated by an OpSwitch Target or Default
396 // block
397 if (!DT.dominates(Target, BB))
398 return false;
399 // excluding the blocks structurally dominated by the OpSwitch
400 // construct’s corresponding merge block.
401 if (DT.dominates(Merge, BB) || BB == Merge)
402 return false;
403 Output.push_back(BB);
404 return true;
405 });
406 return Output;
407 }
408
409 // Splits the given edges by recreating proxy nodes so that the destination
410 // has unique incoming edges from this region.
411 //
412 // clang-format off
413 //
414 // In SPIR-V, constructs must have a single exit/merge.
415 // Given nodes A and B in the construct, a node C outside, and the following edges.
416 // A -> C
417 // B -> C
418 //
419 // In such cases, we must create a new exit node D, that belong to the construct to make is viable:
420 // A -> D -> C
421 // B -> D -> C
422 //
423 // This is fine (assuming C has no PHI nodes), but requires handling the merge instruction here.
424 // By adding a proxy node, we create a regular divergent shape which can easily be regularized later on.
425 // A -> D -> D1 -> C
426 // B -> D -> D2 -> C
427 //
428 // A, B, D belongs to the construct. D is the exit. D1 and D2 are empty.
429 //
430 // clang-format on
431 std::vector<Edge>
432 createAliasBlocksForComplexEdges(std::vector<Edge> Edges) {
433 SmallPtrSet<BasicBlock *, 0> Seen;
434 std::vector<Edge> Output;
435 Output.reserve(Edges.size());
436
437 for (auto &[Src, Dst] : Edges) {
438 auto [Iterator, Inserted] = Seen.insert(Src);
439 if (!Inserted) {
440 // Src already a source node. Cannot have 2 edges from A to B.
441 // Creating alias source block.
443 F.getContext(), Src->getName() + ".new.src", &F);
444 replaceBranchTargets(Src, Dst, NewSrc);
445 IRBuilder<> Builder(NewSrc);
446 Builder.CreateBr(Dst);
447 Src = NewSrc;
448 }
449
450 Output.emplace_back(Src, Dst);
451 }
452
453 return Output;
454 }
455
456 // Given a construct defined by |Header|, and a list of exiting edges
457 // |Edges|, creates a new single exit node, fixing up those edges.
458 BasicBlock *createSingleExitNode(BasicBlock *Header,
459 std::vector<Edge> &Edges) {
460
461 std::vector<Edge> FixedEdges = createAliasBlocksForComplexEdges(Edges);
462
463 std::vector<BasicBlock *> Dsts;
464 DenseMap<BasicBlock *, ConstantInt *> DstToIndex;
465 auto NewExit = BasicBlock::Create(F.getContext(),
466 Header->getName() + ".new.exit", &F);
467 IRBuilder<> ExitBuilder(NewExit);
468 for (auto &[Src, Dst] : FixedEdges) {
469 if (DstToIndex.count(Dst) != 0)
470 continue;
471 DstToIndex.try_emplace(Dst, ExitBuilder.getInt32(DstToIndex.size()));
472 Dsts.push_back(Dst);
473 }
474
475 if (Dsts.size() == 1) {
476 for (auto &[Src, Dst] : FixedEdges) {
477 replaceBranchTargets(Src, Dst, NewExit);
478 }
479 ExitBuilder.CreateBr(Dsts[0]);
480 return NewExit;
481 }
482
483 AllocaInst *Variable = createVariable(F, ExitBuilder.getInt32Ty());
484 for (auto &[Src, Dst] : FixedEdges) {
485 IRBuilder<> B2(Src);
486 B2.SetInsertPoint(Src->getFirstInsertionPt());
487 B2.CreateStore(DstToIndex[Dst], Variable);
488 replaceBranchTargets(Src, Dst, NewExit);
489 }
490
491 Value *Load = ExitBuilder.CreateLoad(ExitBuilder.getInt32Ty(), Variable);
492
493 // If we can avoid an OpSwitch, generate an OpBranch. Reason is some
494 // OpBranch are allowed to exist without a new OpSelectionMerge if one of
495 // the branch is the parent's merge node, while OpSwitches are not.
496 if (Dsts.size() == 2) {
497 Value *Condition =
498 ExitBuilder.CreateCmp(CmpInst::ICMP_EQ, DstToIndex[Dsts[0]], Load);
499 ExitBuilder.CreateCondBr(Condition, Dsts[0], Dsts[1]);
500 return NewExit;
501 }
502
503 SwitchInst *Sw = ExitBuilder.CreateSwitch(Load, Dsts[0], Dsts.size() - 1);
504 for (BasicBlock *BB : drop_begin(Dsts))
505 Sw->addCase(DstToIndex[BB], BB);
506 return NewExit;
507 }
508 };
509
510 // Creates a new basic block in F with a single OpUnreachable instruction.
511 BasicBlock *CreateUnreachable(Function &F) {
512 BasicBlock *BB = BasicBlock::Create(F.getContext(), "unreachable", &F);
513 IRBuilder<> Builder(BB);
514 Builder.CreateUnreachable();
515 return BB;
516 }
517
518 // Add OpLoopMerge instruction on cycles.
519 bool addMergeForLoops(Function &F) {
520 auto *TopLevelRegion = RegionInfo.getTopLevelRegion();
521
522 bool Modified = false;
523 for (auto &BB : F) {
524 // Not a loop header. Ignoring for now.
525 if (!LI.isLoopHeader(&BB))
526 continue;
527 auto *L = LI.getLoopFor(&BB);
528
529 // This loop header is not the entrance of a convergence region. Ignoring
530 // this block.
531 auto *CR = getRegionForHeader(TopLevelRegion, &BB);
532 if (CR == nullptr)
533 continue;
534
535 IRBuilder<> Builder(&BB);
536
537 auto *Merge = getExitFor(CR);
538 // We are indeed in a loop, but there are no exits (infinite loop).
539 // This could be caused by a bad shader, but also could be an artifact
540 // from an earlier optimization. It is not always clear if structurally
541 // reachable means runtime reachable, so we cannot error-out. What we must
542 // do however is to make is legal on the SPIR-V point of view, hence
543 // adding an unreachable merge block.
544 if (Merge == nullptr) {
545 UncondBrInst *Br = cast<UncondBrInst>(BB.getTerminator());
546 Merge = CreateUnreachable(F);
547 Builder.SetInsertPoint(Br);
548 Builder.CreateCondBr(Builder.getFalse(), Merge, Br->getSuccessor(0));
549 Br->eraseFromParent();
550 }
551
552 auto *Continue = L->getLoopLatch();
553
554 Builder.SetInsertPoint(BB.getTerminator());
555 auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
556 auto ContinueAddress = BlockAddress::get(Continue->getParent(), Continue);
557 SmallVector<Value *, 2> Args = {MergeAddress, ContinueAddress};
558 SmallVector<unsigned, 1> LoopControlImms =
560 for (unsigned Imm : LoopControlImms)
561 Args.emplace_back(ConstantInt::get(Builder.getInt32Ty(), Imm));
562 Builder.CreateIntrinsic(Intrinsic::spv_loop_merge, {Args});
563 Modified = true;
564 }
565
566 return Modified;
567 }
568
569 // Adds an OpSelectionMerge to the immediate dominator or each node with an
570 // in-degree of 2 or more which is not already the merge target of an
571 // OpLoopMerge/OpSelectionMerge.
572 bool addMergeForNodesWithMultiplePredecessors(Function &F) {
574 DT.recalculate(F);
575
576 bool Modified = false;
577 for (auto &BB : F) {
578 if (pred_size(&BB) <= 1)
579 continue;
580
581 if (hasLoopMergeInstruction(BB) && pred_size(&BB) <= 2)
582 continue;
583
584 assert(DT.getNode(&BB)->getIDom());
585 BasicBlock *Header = DT.getNode(&BB)->getIDom()->getBlock();
586
587 if (isDefinedAsSelectionMergeBy(*Header, BB))
588 continue;
589
590 IRBuilder<> Builder(Header);
591 Builder.SetInsertPoint(Header->getTerminator());
592
593 auto MergeAddress = BlockAddress::get(BB.getParent(), &BB);
594 createOpSelectMerge(&Builder, MergeAddress);
595
596 Modified = true;
597 }
598
599 return Modified;
600 }
601
602 // When a block has multiple OpSelectionMerge/OpLoopMerge instructions, sorts
603 // them to put the "largest" first. A merge instruction is defined as larger
604 // than another when its target merge block post-dominates the other target's
605 // merge block. (This ordering should match the nesting ordering of the source
606 // HLSL).
607 bool sortSelectionMerge(PartialOrderingVisitor &Visitor, BasicBlock &Block) {
608 std::vector<Instruction *> MergeInstructions;
609 for (Instruction &I : Block)
610 if (isMergeInstruction(&I))
611 MergeInstructions.push_back(&I);
612
613 if (MergeInstructions.size() <= 1)
614 return false;
615
616 Instruction *InsertionPoint = *MergeInstructions.begin();
617
618 llvm::sort(MergeInstructions,
619 [&Visitor](Instruction *Left, Instruction *Right) {
620 if (Left == Right)
621 return false;
624 return !Visitor.compare(RightMerge, LeftMerge);
625 });
626
627 for (Instruction *I : MergeInstructions) {
628 I->moveBefore(InsertionPoint->getIterator());
629 InsertionPoint = I;
630 }
631
632 return true;
633 }
634
635 // Sorts selection merge headers in |F|.
636 // A is sorted before B if the merge block designated by B is an ancestor of
637 // the one designated by A.
638 bool sortSelectionMergeHeaders(Function &F) {
639 bool Modified = false;
640 PartialOrderingVisitor Visitor(F);
641 for (BasicBlock &BB : F) {
642 Modified |= sortSelectionMerge(Visitor, BB);
643 }
644 return Modified;
645 }
646
647 // Split basic blocks containing multiple OpLoopMerge/OpSelectionMerge
648 // instructions so each basic block contains only a single merge instruction.
649 bool splitBlocksWithMultipleHeaders(Function &F) {
650 std::stack<BasicBlock *> Work;
651 for (auto &BB : F) {
652 std::vector<Instruction *> MergeInstructions = getMergeInstructions(BB);
653 if (MergeInstructions.size() <= 1)
654 continue;
655 Work.push(&BB);
656 }
657
658 const bool Modified = Work.size() > 0;
659 while (Work.size() > 0) {
660 BasicBlock *Header = Work.top();
661 Work.pop();
662
663 std::vector<Instruction *> MergeInstructions =
664 getMergeInstructions(*Header);
665 for (unsigned i = 1; i < MergeInstructions.size(); i++) {
666 BasicBlock *NewBlock =
667 Header->splitBasicBlock(MergeInstructions[i], "new.header");
668
669 if (getDesignatedContinueBlock(MergeInstructions[0]) == nullptr) {
670 BasicBlock *Unreachable = CreateUnreachable(F);
671
672 Instruction *Term = Header->getTerminator();
673 IRBuilder<> Builder(Header);
674 Builder.SetInsertPoint(Term);
675 Builder.CreateCondBr(Builder.getTrue(), NewBlock, Unreachable);
676 Term->eraseFromParent();
677 }
678
679 Header = NewBlock;
680 }
681 }
682
683 return Modified;
684 }
685
686 // Adds an OpSelectionMerge to each block with an out-degree >= 2 which
687 // doesn't already have an OpSelectionMerge.
688 bool addMergeForDivergentBlocks(Function &F) {
690 PDT.recalculate(F);
691 bool Modified = false;
692
693 auto MergeBlocks = getMergeBlocks(F);
694 auto ContinueBlocks = getContinueBlocks(F);
695
696 for (auto &BB : F) {
697 if (getMergeInstructions(BB).size() != 0)
698 continue;
699
700 std::vector<BasicBlock *> Candidates;
701 for (BasicBlock *Successor : successors(&BB)) {
702 if (MergeBlocks.contains(Successor))
703 continue;
704 if (ContinueBlocks.contains(Successor))
705 continue;
706 Candidates.push_back(Successor);
707 }
708
709 if (Candidates.size() <= 1)
710 continue;
711
712 Modified = true;
713 BasicBlock *Merge = Candidates[0];
714
715 auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
716 IRBuilder<> Builder(&BB);
717 Builder.SetInsertPoint(BB.getTerminator());
718 createOpSelectMerge(&Builder, MergeAddress);
719 }
720
721 return Modified;
722 }
723
724 // Gather all the exit nodes for the construct header by |Header| and
725 // containing the blocks |Construct|.
726 std::vector<Edge> getExitsFrom(const BlockSet &Construct,
727 BasicBlock &Header) {
728 std::vector<Edge> Output;
729 visit(Header, [&](BasicBlock *Item) {
730 if (Construct.count(Item) == 0)
731 return false;
732
733 for (BasicBlock *Successor : successors(Item)) {
734 if (Construct.count(Successor) == 0)
735 Output.emplace_back(Item, Successor);
736 }
737 return true;
738 });
739
740 return Output;
741 }
742
743 // Build a divergent construct tree searching from |BB|.
744 // If |Parent| is not null, this tree is attached to the parent's tree.
745 void constructDivergentConstruct(BlockSet &Visited, Splitter &S,
746 BasicBlock *BB, DivergentConstruct *Parent) {
747 if (Visited.count(BB) != 0)
748 return;
749 Visited.insert(BB);
750
751 auto MIS = getMergeInstructions(*BB);
752 if (MIS.size() == 0) {
753 for (BasicBlock *Successor : successors(BB))
754 constructDivergentConstruct(Visited, S, Successor, Parent);
755 return;
756 }
757
758 assert(MIS.size() == 1);
759 Instruction *MI = MIS[0];
760
763
764 auto Output = std::make_unique<DivergentConstruct>();
765 Output->Header = BB;
766 Output->Merge = Merge;
767 Output->Continue = Continue;
768 Output->Parent = Parent;
769
770 constructDivergentConstruct(Visited, S, Merge, Parent);
771 if (Continue)
772 constructDivergentConstruct(Visited, S, Continue, Output.get());
773
774 for (BasicBlock *Successor : successors(BB))
775 constructDivergentConstruct(Visited, S, Successor, Output.get());
776
777 if (Parent)
778 Parent->Children.emplace_back(std::move(Output));
779 }
780
781 // Returns the blocks belonging to the divergent construct |Node|.
782 BlockSet getConstructBlocks(Splitter &S, DivergentConstruct *Node) {
783 assert(Node->Header && Node->Merge);
784
785 if (Node->Continue) {
786 auto LoopBlocks = S.getLoopConstructBlocks(Node->Header, Node->Merge);
787 return BlockSet(LoopBlocks.begin(), LoopBlocks.end());
788 }
789
790 auto SelectionBlocks = S.getSelectionConstructBlocks(Node);
791 return BlockSet(SelectionBlocks.begin(), SelectionBlocks.end());
792 }
793
794 // Fixup the construct |Node| to respect a set of rules defined by the SPIR-V
795 // spec.
796 bool fixupConstruct(Splitter &S, DivergentConstruct *Node) {
797 bool Modified = false;
798 for (auto &Child : Node->Children)
799 Modified |= fixupConstruct(S, Child.get());
800
801 // This construct is the root construct. Does not represent any real
802 // construct, just a way to access the first level of the forest.
803 if (Node->Parent == nullptr)
804 return Modified;
805
806 // This node's parent is the root. Meaning this is a top-level construct.
807 // There can be multiple exists, but all are guaranteed to exit at most 1
808 // construct since we are at first level.
809 if (Node->Parent->Header == nullptr)
810 return Modified;
811
812 // Health check for the structure.
813 assert(Node->Header && Node->Merge);
814 assert(Node->Parent->Header && Node->Parent->Merge);
815
816 BlockSet ConstructBlocks = getConstructBlocks(S, Node);
817 auto Edges = getExitsFrom(ConstructBlocks, *Node->Header);
818
819 // No edges exiting the construct.
820 if (Edges.size() < 1)
821 return Modified;
822
823 bool HasBadEdge = Node->Merge == Node->Parent->Merge ||
824 Node->Merge == Node->Parent->Continue;
825 // BasicBlock *Target = Edges[0].second;
826 for (auto &[Src, Dst] : Edges) {
827 // - Breaking from a selection construct: S is a selection construct, S is
828 // the innermost structured
829 // control-flow construct containing A, and B is the merge block for S
830 // - Breaking from the innermost loop: S is the innermost loop construct
831 // containing A,
832 // and B is the merge block for S
833 if (Node->Merge == Dst)
834 continue;
835
836 // Entering the innermost loop’s continue construct: S is the innermost
837 // loop construct containing A, and B is the continue target for S
838 if (Node->Continue == Dst)
839 continue;
840
841 // TODO: what about cases branching to another case in the switch? Seems
842 // to work, but need to double check.
843 HasBadEdge = true;
844 }
845
846 if (!HasBadEdge)
847 return Modified;
848
849 // Create a single exit node gathering all exit edges.
850 BasicBlock *NewExit = S.createSingleExitNode(Node->Header, Edges);
851
852 // Fixup this construct's merge node to point to the new exit.
853 // Note: this algorithm fixes inner-most divergence construct first. So
854 // recursive structures sharing a single merge node are fixed from the
855 // inside toward the outside.
856 auto MergeInstructions = getMergeInstructions(*Node->Header);
857 assert(MergeInstructions.size() == 1);
858 Instruction *I = MergeInstructions[0];
859 BlockAddress *BA = cast<BlockAddress>(I->getOperand(0));
860 if (BA->getBasicBlock() == Node->Merge) {
861 auto MergeAddress = BlockAddress::get(NewExit->getParent(), NewExit);
862 I->setOperand(0, MergeAddress);
863 }
864
865 // Clean up of the possible dangling BockAddr operands to prevent MIR
866 // comments about "address of removed block taken".
867 if (!BA->isConstantUsed())
868 BA->destroyConstant();
869
870 Node->Merge = NewExit;
871 // Regenerate the dom trees.
872 S.invalidate();
873 return true;
874 }
875
876 bool splitCriticalEdges(Function &F) {
877 Splitter S(F);
878
879 DivergentConstruct Root;
880 BlockSet Visited;
881 constructDivergentConstruct(Visited, S, &*F.begin(), &Root);
882 return fixupConstruct(S, &Root);
883 }
884
885 // Simplify branches when possible:
886 // - if the 2 sides of a conditional branch are the same, transforms it to an
887 // unconditional branch.
888 // - if a switch has only 2 distinct successors, converts it to a conditional
889 // branch.
890 bool simplifyBranches(Function &F) {
891 bool Modified = false;
892
893 for (BasicBlock &BB : F) {
894 SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator());
895 if (!SI)
896 continue;
897 if (SI->getNumCases() > 1)
898 continue;
899
900 Modified = true;
901 IRBuilder<> Builder(&BB);
902 Builder.SetInsertPoint(SI);
903
904 if (SI->getNumCases() == 0) {
905 Builder.CreateBr(SI->getDefaultDest());
906 } else {
907 Value *Condition =
908 Builder.CreateCmp(CmpInst::ICMP_EQ, SI->getCondition(),
909 SI->case_begin()->getCaseValue());
910 Builder.CreateCondBr(Condition, SI->case_begin()->getCaseSuccessor(),
911 SI->getDefaultDest());
912 }
913 SI->eraseFromParent();
914 }
915
916 return Modified;
917 }
918
919 // Makes sure every case target in |F| is unique. If 2 cases branch to the
920 // same basic block, one of the targets is updated so it jumps to a new basic
921 // block ending with a single unconditional branch to the original target.
922 bool splitSwitchCases(Function &F) {
923 bool Modified = false;
924
925 for (BasicBlock &BB : F) {
926 SwitchInst *SI = dyn_cast<SwitchInst>(BB.getTerminator());
927 if (!SI)
928 continue;
929
930 BlockSet Seen;
931 Seen.insert(SI->getDefaultDest());
932
933 auto It = SI->case_begin();
934 while (It != SI->case_end()) {
935 BasicBlock *Target = It->getCaseSuccessor();
936
937 // Don't Split. Just remove cases branching to the default destination
938 // to prevent spurious extra successors thus preserving single-exit
939 // convergence regions (i.e. if a merged exit is default & a case).
940 if (Target == SI->getDefaultDest()) {
941 Modified = true;
942 It = SI->removeCase(It);
943 continue;
944 }
945
946 if (Seen.count(Target) == 0) {
947 Seen.insert(Target);
948 ++It;
949 continue;
950 }
951
952 Modified = true;
953 BasicBlock *NewTarget =
954 BasicBlock::Create(F.getContext(), "new.sw.case", &F);
955 IRBuilder<> Builder(NewTarget);
956 Builder.CreateBr(Target);
957 SI->addCase(It->getCaseValue(), NewTarget);
958 It = SI->removeCase(It);
959 }
960 }
961
962 return Modified;
963 }
964
965 // Removes blocks not contributing to any structured CFG. This assumes there
966 // is no PHI nodes.
967 bool removeUselessBlocks(Function &F) {
968 std::vector<BasicBlock *> ToRemove;
969
970 auto MergeBlocks = getMergeBlocks(F);
971 auto ContinueBlocks = getContinueBlocks(F);
972
973 for (BasicBlock &BB : F) {
974 if (BB.size() != 1)
975 continue;
976
978 continue;
979
980 if (MergeBlocks.count(&BB) != 0 || ContinueBlocks.count(&BB) != 0)
981 continue;
982
983 if (BB.getUniqueSuccessor() == nullptr)
984 continue;
985
987 std::vector<BasicBlock *> Predecessors(predecessors(&BB).begin(),
988 predecessors(&BB).end());
989 for (BasicBlock *Predecessor : Predecessors)
990 replaceBranchTargets(Predecessor, &BB, Successor);
991 ToRemove.push_back(&BB);
992 }
993
994 for (BasicBlock *BB : ToRemove)
995 BB->eraseFromParent();
996
997 return ToRemove.size() != 0;
998 }
999
1000 bool addHeaderToRemainingDivergentDAG(Function &F) {
1001 bool Modified = false;
1002
1003 auto MergeBlocks = getMergeBlocks(F);
1004 auto ContinueBlocks = getContinueBlocks(F);
1005 auto HeaderBlocks = getHeaderBlocks(F);
1006
1009 PDT.recalculate(F);
1010 DT.recalculate(F);
1011
1012 for (BasicBlock &BB : F) {
1013 if (HeaderBlocks.count(&BB) != 0)
1014 continue;
1015 if (succ_size(&BB) < 2)
1016 continue;
1017
1018 size_t CandidateEdges = 0;
1019 for (BasicBlock *Successor : successors(&BB)) {
1020 if (MergeBlocks.count(Successor) != 0 ||
1021 ContinueBlocks.count(Successor) != 0)
1022 continue;
1023 if (HeaderBlocks.count(Successor) != 0)
1024 continue;
1025 CandidateEdges += 1;
1026 }
1027
1028 if (CandidateEdges <= 1)
1029 continue;
1030
1031 BasicBlock *Header = &BB;
1032 BasicBlock *Merge = PDT.getNode(&BB)->getIDom()->getBlock();
1033
1034 bool HasBadBlock = false;
1035 visit(*Header, [&](const BasicBlock *Node) {
1036 if (DT.dominates(Header, Node))
1037 return false;
1038 if (PDT.dominates(Merge, Node))
1039 return false;
1040 if (Node == Header || Node == Merge)
1041 return true;
1042
1043 HasBadBlock |= MergeBlocks.count(Node) != 0 ||
1044 ContinueBlocks.count(Node) != 0 ||
1045 HeaderBlocks.count(Node) != 0;
1046 return !HasBadBlock;
1047 });
1048
1049 if (HasBadBlock)
1050 continue;
1051
1052 Modified = true;
1053
1054 if (Merge == nullptr) {
1055 Merge = *successors(Header).begin();
1056 IRBuilder<> Builder(Header);
1057 Builder.SetInsertPoint(Header->getTerminator());
1058
1059 auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
1060 createOpSelectMerge(&Builder, MergeAddress);
1061 continue;
1062 }
1063
1064 Instruction *SplitInstruction = Merge->getTerminator();
1065 if (isMergeInstruction(SplitInstruction->getPrevNode()))
1066 SplitInstruction = SplitInstruction->getPrevNode();
1067 BasicBlock *NewMerge =
1068 Merge->splitBasicBlockBefore(SplitInstruction, "new.merge");
1069
1070 IRBuilder<> Builder(Header);
1071 Builder.SetInsertPoint(Header->getTerminator());
1072
1073 auto MergeAddress = BlockAddress::get(NewMerge->getParent(), NewMerge);
1074 createOpSelectMerge(&Builder, MergeAddress);
1075 }
1076
1077 return Modified;
1078 }
1079
1080public:
1081 SPIRVStructurizerImpl(LoopInfo &LI, ConvergenceRegionInfo &RegionInfo)
1082 : LI(LI), RegionInfo(RegionInfo) {}
1083
1084 bool run(Function &F) {
1085 bool Modified = false;
1086
1087 // In LLVM, Switches are allowed to have several cases branching to the same
1088 // basic block. This is allowed in SPIR-V, but can make structurizing SPIR-V
1089 // harder, so first remove edge cases.
1090 Modified |= splitSwitchCases(F);
1091
1092 // LLVM allows conditional branches to have both side jumping to the same
1093 // block. It also allows switched to have a single default, or just one
1094 // case. Cleaning this up now.
1095 Modified |= simplifyBranches(F);
1096
1097 // At this state, we should have a reducible CFG with cycles.
1098 // STEP 1: Adding OpLoopMerge instructions to loop headers.
1099 Modified |= addMergeForLoops(F);
1100
1101 // STEP 2: adding OpSelectionMerge to each node with an in-degree >= 2.
1102 Modified |= addMergeForNodesWithMultiplePredecessors(F);
1103
1104 // STEP 3:
1105 // Sort selection merge, the largest construct goes first.
1106 // This simplifies the next step.
1107 Modified |= sortSelectionMergeHeaders(F);
1108
1109 // STEP 4: As this stage, we can have a single basic block with multiple
1110 // OpLoopMerge/OpSelectionMerge instructions. Splitting this block so each
1111 // BB has a single merge instruction.
1112 Modified |= splitBlocksWithMultipleHeaders(F);
1113
1114 // STEP 5: In the previous steps, we added merge blocks the loops and
1115 // natural merge blocks (in-degree >= 2). What remains are conditions with
1116 // an exiting branch (return, unreachable). In such case, we must start from
1117 // the header, and add headers to divergent construct with no headers.
1118 Modified |= addMergeForDivergentBlocks(F);
1119
1120 // STEP 6: At this stage, we have several divergent construct defines by a
1121 // header and a merge block. But their boundaries have no constraints: a
1122 // construct exit could be outside of the parents' construct exit. Such
1123 // edges are called critical edges. What we need is to split those edges
1124 // into several parts. Each part exiting the parent's construct by its merge
1125 // block.
1127
1128 // STEP 7: The previous steps possibly created a lot of "proxy" blocks.
1129 // Blocks with a single unconditional branch, used to create a valid
1130 // divergent construct tree. Some nodes are still requires (e.g: nodes
1131 // allowing a valid exit through the parent's merge block). But some are
1132 // left-overs of past transformations, and could cause actual validation
1133 // issues. E.g: the SPIR-V spec allows a construct to break to the parents
1134 // loop construct without an OpSelectionMerge, but this requires a straight
1135 // jump. If a proxy block lies between the conditional branch and the
1136 // parent's merge, the CFG is not valid.
1137 Modified |= removeUselessBlocks(F);
1138
1139 // STEP 8: Final fix-up steps: our tree boundaries are correct, but some
1140 // blocks are branching with no header. Those are often simple conditional
1141 // branches with 1 or 2 returning edges. Adding a header for those.
1142 Modified |= addHeaderToRemainingDivergentDAG(F);
1143
1144 // STEP 9: sort basic blocks to match both the LLVM & SPIR-V requirements.
1145 Modified |= sortBlocks(F);
1146
1147 return Modified;
1148 }
1149
1150 void createOpSelectMerge(IRBuilder<> *Builder, BlockAddress *MergeAddress) {
1151 Instruction *BBTerminatorInst = Builder->GetInsertBlock()->getTerminator();
1152
1153 MDNode *MDNode = BBTerminatorInst->getMetadata("hlsl.controlflow.hint");
1154
1155 ConstantInt *BranchHint = ConstantInt::get(Builder->getInt32Ty(), 0);
1156
1157 if (MDNode) {
1158 assert(MDNode->getNumOperands() == 2 &&
1159 "invalid metadata hlsl.controlflow.hint");
1160 BranchHint = mdconst::extract<ConstantInt>(MDNode->getOperand(1));
1161 }
1162
1163 SmallVector<Value *, 2> Args = {MergeAddress, BranchHint};
1164
1165 Builder->CreateIntrinsic(Intrinsic::spv_selection_merge,
1166 {MergeAddress->getType()}, Args);
1167 }
1168};
1169
1170class SPIRVStructurizer : public FunctionPass {
1171public:
1172 static char ID;
1173
1174 SPIRVStructurizer() : FunctionPass(ID) {}
1175
1176 bool runOnFunction(Function &F) override {
1177 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1178 ConvergenceRegionInfo &RegionInfo =
1179 getAnalysis<SPIRVConvergenceRegionAnalysisWrapperPass>()
1180 .getRegionInfo();
1181 return SPIRVStructurizerImpl(LI, RegionInfo).run(F);
1182 }
1183
1184 void getAnalysisUsage(AnalysisUsage &AU) const override {
1185 AU.addRequired<DominatorTreeWrapperPass>();
1186 AU.addRequired<LoopInfoWrapperPass>();
1187 AU.addRequired<SPIRVConvergenceRegionAnalysisWrapperPass>();
1188
1189 AU.addPreserved<SPIRVConvergenceRegionAnalysisWrapperPass>();
1190 FunctionPass::getAnalysisUsage(AU);
1191 }
1192};
1193} // anonymous namespace
1194
1195char SPIRVStructurizer::ID = 0;
1196
1197INITIALIZE_PASS_BEGIN(SPIRVStructurizer, "spirv-structurizer",
1198 "structurize SPIRV", false, false)
1199INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
1203
1204INITIALIZE_PASS_END(SPIRVStructurizer, "spirv-structurizer",
1205 "structurize SPIRV", false, false)
1206
1208 return new SPIRVStructurizer();
1209}
1210
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
#define op(i)
IRTranslator LLVM IR MI
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static bool splitCriticalEdges(CallBrInst *CBR, DominatorTree *DT)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
R600 Clause Merge
static BasicBlock * getDesignatedMergeBlock(Instruction *I)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static std::vector< Instruction * > getMergeInstructions(BasicBlock &BB)
SmallPtrSet< BasicBlock *, 0 > BlockSet
static BasicBlock * getDesignatedContinueBlock(Instruction *I)
static const ConvergenceRegion * getRegionForHeader(const ConvergenceRegion *Node, BasicBlock *BB)
static bool hasLoopMergeInstruction(BasicBlock &BB)
static SmallPtrSet< BasicBlock *, 2 > getContinueBlocks(Function &F)
static SmallPtrSet< BasicBlock *, 2 > getMergeBlocks(Function &F)
static SmallPtrSet< BasicBlock *, 2 > getHeaderBlocks(Function &F)
static bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge)
static void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget, BasicBlock *NewTarget)
static bool isMergeInstruction(Instruction *I)
static BasicBlock * getExitFor(const ConvergenceRegion *CR)
static void replaceIfBranchTargets(BasicBlock *BB, BasicBlock *OldTarget, BasicBlock *NewTarget)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
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.
size_t size() const
Definition BasicBlock.h:482
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
The address of a basic block.
Definition Constants.h:1088
BasicBlock * getBasicBlock() const
Definition Constants.h:1125
static LLVM_ABI BlockAddress * get(Function *F, BasicBlock *BB)
Return a BlockAddress for the specified function and basic block.
This is an important base class in LLVM.
Definition Constant.h:43
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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
unsigned size() const
Definition DenseMap.h:172
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:219
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.
Definition Dominators.h:306
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:534
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
A wrapper class for inspecting calls to intrinsic functions.
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:587
The legacy pass manager's analysis pass to compute loop information.
Definition LoopInfo.h:612
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
bool compare(const BasicBlock *LHS, const BasicBlock *RHS) const
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Result run(Function &F, FunctionAnalysisManager &AM)
PreservedAnalyses run(Function &M, FunctionAnalysisManager &AM)
size_type size() const
Definition SmallPtrSet.h:99
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.
iterator begin() const
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.
BasicBlock * getSuccessor(unsigned i=0) const
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
self_iterator getIterator()
Definition ilist_node.h:123
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
PostDomTreeBase< BasicBlock > BBPostDomTree
Definition Dominators.h:56
DomTreeBase< BasicBlock > BBDomTree
Definition Dominators.h:55
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
DXILDebugInfoMap run(Module &M)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
iterator end() const
Definition BasicBlock.h:89
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
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.
Definition STLExtras.h:315
FunctionPass * createSPIRVStructurizerPass()
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.
Definition STLExtras.h:1669
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
bool sortBlocks(Function &F)
auto pred_size(const MachineBasicBlock *BB)
AllocaInst * createVariable(Function &F, Type *Type)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(MDNode *LoopMD)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
auto succ_size(const MachineBasicBlock *BB)
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...
Definition Casting.h:547
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.
Definition Casting.h:559
auto predecessors(const MachineBasicBlock *BB)
@ Continue
Definition DWP.h:26
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.