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