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