xref: /llvm-project/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp (revision 304a99091c84f303ff5037dc6bf5455e4cfde7a1)
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 
11 #include "Analysis/SPIRVConvergenceRegionAnalysis.h"
12 #include "SPIRV.h"
13 #include "SPIRVStructurizerWrapper.h"
14 #include "SPIRVSubtarget.h"
15 #include "SPIRVTargetMachine.h"
16 #include "SPIRVUtils.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/SmallPtrSet.h"
19 #include "llvm/Analysis/LoopInfo.h"
20 #include "llvm/CodeGen/IntrinsicLowering.h"
21 #include "llvm/IR/CFG.h"
22 #include "llvm/IR/Dominators.h"
23 #include "llvm/IR/IRBuilder.h"
24 #include "llvm/IR/IntrinsicInst.h"
25 #include "llvm/IR/Intrinsics.h"
26 #include "llvm/IR/IntrinsicsSPIRV.h"
27 #include "llvm/IR/LegacyPassManager.h"
28 #include "llvm/InitializePasses.h"
29 #include "llvm/PassRegistry.h"
30 #include "llvm/Transforms/Utils.h"
31 #include "llvm/Transforms/Utils/Cloning.h"
32 #include "llvm/Transforms/Utils/LoopSimplify.h"
33 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
34 #include <queue>
35 #include <stack>
36 #include <unordered_set>
37 
38 using namespace llvm;
39 using namespace SPIRV;
40 
41 namespace llvm {
42 
43 void initializeSPIRVStructurizerPass(PassRegistry &);
44 
45 namespace {
46 
47 using BlockSet = std::unordered_set<BasicBlock *>;
48 using Edge = std::pair<BasicBlock *, BasicBlock *>;
49 
50 // Helper function to do a partial order visit from the block |Start|, calling
51 // |Op| on each visited node.
52 void partialOrderVisit(BasicBlock &Start,
53                        std::function<bool(BasicBlock *)> Op) {
54   PartialOrderingVisitor V(*Start.getParent());
55   V.partialOrderVisit(Start, Op);
56 }
57 
58 // Returns the exact convergence region in the tree defined by `Node` for which
59 // `BB` is the header, nullptr otherwise.
60 const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
61                                             BasicBlock *BB) {
62   if (Node->Entry == BB)
63     return Node;
64 
65   for (auto *Child : Node->Children) {
66     const auto *CR = getRegionForHeader(Child, BB);
67     if (CR != nullptr)
68       return CR;
69   }
70   return nullptr;
71 }
72 
73 // Returns the single BasicBlock exiting the convergence region `CR`,
74 // nullptr if no such exit exists.
75 BasicBlock *getExitFor(const ConvergenceRegion *CR) {
76   std::unordered_set<BasicBlock *> ExitTargets;
77   for (BasicBlock *Exit : CR->Exits) {
78     for (BasicBlock *Successor : successors(Exit)) {
79       if (CR->Blocks.count(Successor) == 0)
80         ExitTargets.insert(Successor);
81     }
82   }
83 
84   assert(ExitTargets.size() <= 1);
85   if (ExitTargets.size() == 0)
86     return nullptr;
87 
88   return *ExitTargets.begin();
89 }
90 
91 // Returns the merge block designated by I if I is a merge instruction, nullptr
92 // otherwise.
93 BasicBlock *getDesignatedMergeBlock(Instruction *I) {
94   IntrinsicInst *II = dyn_cast_or_null<IntrinsicInst>(I);
95   if (II == nullptr)
96     return nullptr;
97 
98   if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
99       II->getIntrinsicID() != Intrinsic::spv_selection_merge)
100     return nullptr;
101 
102   BlockAddress *BA = cast<BlockAddress>(II->getOperand(0));
103   return BA->getBasicBlock();
104 }
105 
106 // Returns the continue block designated by I if I is an OpLoopMerge, nullptr
107 // otherwise.
108 BasicBlock *getDesignatedContinueBlock(Instruction *I) {
109   IntrinsicInst *II = dyn_cast_or_null<IntrinsicInst>(I);
110   if (II == nullptr)
111     return nullptr;
112 
113   if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
114     return nullptr;
115 
116   BlockAddress *BA = cast<BlockAddress>(II->getOperand(1));
117   return BA->getBasicBlock();
118 }
119 
120 // Returns true if Header has one merge instruction which designated Merge as
121 // merge block.
122 bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
123   for (auto &I : Header) {
124     BasicBlock *MB = getDesignatedMergeBlock(&I);
125     if (MB == &Merge)
126       return true;
127   }
128   return false;
129 }
130 
131 // Returns true if the BB has one OpLoopMerge instruction.
132 bool hasLoopMergeInstruction(BasicBlock &BB) {
133   for (auto &I : BB)
134     if (getDesignatedContinueBlock(&I))
135       return true;
136   return false;
137 }
138 
139 // Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
140 // otherwise.
141 bool isMergeInstruction(Instruction *I) {
142   return getDesignatedMergeBlock(I) != nullptr;
143 }
144 
145 // Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
146 // instruction.
147 SmallPtrSet<BasicBlock *, 2> getHeaderBlocks(Function &F) {
148   SmallPtrSet<BasicBlock *, 2> Output;
149   for (BasicBlock &BB : F) {
150     for (Instruction &I : BB) {
151       if (getDesignatedMergeBlock(&I) != nullptr)
152         Output.insert(&BB);
153     }
154   }
155   return Output;
156 }
157 
158 // Returns all basic blocks in |F| referenced by at least 1
159 // OpSelectionMerge/OpLoopMerge instruction.
160 SmallPtrSet<BasicBlock *, 2> getMergeBlocks(Function &F) {
161   SmallPtrSet<BasicBlock *, 2> Output;
162   for (BasicBlock &BB : F) {
163     for (Instruction &I : BB) {
164       BasicBlock *MB = getDesignatedMergeBlock(&I);
165       if (MB != nullptr)
166         Output.insert(MB);
167     }
168   }
169   return Output;
170 }
171 
172 // Return all the merge instructions contained in BB.
173 // Note: the SPIR-V spec doesn't allow a single BB to contain more than 1 merge
174 // instruction, but this can happen while we structurize the CFG.
175 std::vector<Instruction *> getMergeInstructions(BasicBlock &BB) {
176   std::vector<Instruction *> Output;
177   for (Instruction &I : BB)
178     if (isMergeInstruction(&I))
179       Output.push_back(&I);
180   return Output;
181 }
182 
183 // Returns all basic blocks in |F| referenced as continue target by at least 1
184 // OpLoopMerge instruction.
185 SmallPtrSet<BasicBlock *, 2> getContinueBlocks(Function &F) {
186   SmallPtrSet<BasicBlock *, 2> Output;
187   for (BasicBlock &BB : F) {
188     for (Instruction &I : BB) {
189       BasicBlock *MB = getDesignatedContinueBlock(&I);
190       if (MB != nullptr)
191         Output.insert(MB);
192     }
193   }
194   return Output;
195 }
196 
197 // Do a preorder traversal of the CFG starting from the BB |Start|.
198 // point. Calls |op| on each basic block encountered during the traversal.
199 void visit(BasicBlock &Start, std::function<bool(BasicBlock *)> op) {
200   std::stack<BasicBlock *> ToVisit;
201   SmallPtrSet<BasicBlock *, 8> Seen;
202 
203   ToVisit.push(&Start);
204   Seen.insert(ToVisit.top());
205   while (ToVisit.size() != 0) {
206     BasicBlock *BB = ToVisit.top();
207     ToVisit.pop();
208 
209     if (!op(BB))
210       continue;
211 
212     for (auto Succ : successors(BB)) {
213       if (Seen.contains(Succ))
214         continue;
215       ToVisit.push(Succ);
216       Seen.insert(Succ);
217     }
218   }
219 }
220 
221 // Replaces the conditional and unconditional branch targets of |BB| by
222 // |NewTarget| if the target was |OldTarget|. This function also makes sure the
223 // associated merge instruction gets updated accordingly.
224 void replaceIfBranchTargets(BasicBlock *BB, BasicBlock *OldTarget,
225                             BasicBlock *NewTarget) {
226   auto *BI = cast<BranchInst>(BB->getTerminator());
227 
228   // 1. Replace all matching successors.
229   for (size_t i = 0; i < BI->getNumSuccessors(); i++) {
230     if (BI->getSuccessor(i) == OldTarget)
231       BI->setSuccessor(i, NewTarget);
232   }
233 
234   // Branch was unconditional, no fixup required.
235   if (BI->isUnconditional())
236     return;
237 
238   // Branch had 2 successors, maybe now both are the same?
239   if (BI->getSuccessor(0) != BI->getSuccessor(1))
240     return;
241 
242   // Note: we may end up here because the original IR had such branches.
243   // This means Target is not necessarily equal to NewTarget.
244   IRBuilder<> Builder(BB);
245   Builder.SetInsertPoint(BI);
246   Builder.CreateBr(BI->getSuccessor(0));
247   BI->eraseFromParent();
248 
249   // The branch was the only instruction, nothing else to do.
250   if (BB->size() == 1)
251     return;
252 
253   // Otherwise, we need to check: was there an OpSelectionMerge before this
254   // branch? If we removed the OpBranchConditional, we must also remove the
255   // OpSelectionMerge. This is not valid for OpLoopMerge:
256   IntrinsicInst *II =
257       dyn_cast<IntrinsicInst>(BB->getTerminator()->getPrevNode());
258   if (!II || II->getIntrinsicID() != Intrinsic::spv_selection_merge)
259     return;
260 
261   Constant *C = cast<Constant>(II->getOperand(0));
262   II->eraseFromParent();
263   if (!C->isConstantUsed())
264     C->destroyConstant();
265 }
266 
267 // Replaces the target of branch instruction in |BB| with |NewTarget| if it
268 // was |OldTarget|. This function also fixes the associated merge instruction.
269 // Note: this function does not simplify branching instructions, it only updates
270 // targets. See also: simplifyBranches.
271 void replaceBranchTargets(BasicBlock *BB, BasicBlock *OldTarget,
272                           BasicBlock *NewTarget) {
273   auto *T = BB->getTerminator();
274   if (isa<ReturnInst>(T))
275     return;
276 
277   if (isa<BranchInst>(T))
278     return replaceIfBranchTargets(BB, OldTarget, NewTarget);
279 
280   if (auto *SI = dyn_cast<SwitchInst>(T)) {
281     for (size_t i = 0; i < SI->getNumSuccessors(); i++) {
282       if (SI->getSuccessor(i) == OldTarget)
283         SI->setSuccessor(i, NewTarget);
284     }
285     return;
286   }
287 
288   assert(false && "Unhandled terminator type.");
289 }
290 
291 } // anonymous namespace
292 
293 // Given a reducible CFG, produces a structurized CFG in the SPIR-V sense,
294 // adding merge instructions when required.
295 class SPIRVStructurizer : public FunctionPass {
296 
297   struct DivergentConstruct;
298   // Represents a list of condition/loops/switch constructs.
299   // See SPIR-V 2.11.2. Structured Control-flow Constructs for the list of
300   // constructs.
301   using ConstructList = std::vector<std::unique_ptr<DivergentConstruct>>;
302 
303   // Represents a divergent construct in the SPIR-V sense.
304   // Such constructs are represented by a header (entry), a merge block (exit),
305   // and possibly a continue block (back-edge). A construct can contain other
306   // constructs, but their boundaries do not cross.
307   struct DivergentConstruct {
308     BasicBlock *Header = nullptr;
309     BasicBlock *Merge = nullptr;
310     BasicBlock *Continue = nullptr;
311 
312     DivergentConstruct *Parent = nullptr;
313     ConstructList Children;
314   };
315 
316   // An helper class to clean the construct boundaries.
317   // It is used to gather the list of blocks that should belong to each
318   // divergent construct, and possibly modify CFG edges when exits would cross
319   // the boundary of multiple constructs.
320   struct Splitter {
321     Function &F;
322     LoopInfo &LI;
323     DomTreeBuilder::BBDomTree DT;
324     DomTreeBuilder::BBPostDomTree PDT;
325 
326     Splitter(Function &F, LoopInfo &LI) : F(F), LI(LI) { invalidate(); }
327 
328     void invalidate() {
329       PDT.recalculate(F);
330       DT.recalculate(F);
331     }
332 
333     // Returns the list of blocks that belong to a SPIR-V loop construct,
334     // including the continue construct.
335     std::vector<BasicBlock *> getLoopConstructBlocks(BasicBlock *Header,
336                                                      BasicBlock *Merge) {
337       assert(DT.dominates(Header, Merge));
338       std::vector<BasicBlock *> Output;
339       partialOrderVisit(*Header, [&](BasicBlock *BB) {
340         if (BB == Merge)
341           return false;
342         if (DT.dominates(Merge, BB) || !DT.dominates(Header, BB))
343           return false;
344         Output.push_back(BB);
345         return true;
346       });
347       return Output;
348     }
349 
350     // Returns the list of blocks that belong to a SPIR-V selection construct.
351     std::vector<BasicBlock *>
352     getSelectionConstructBlocks(DivergentConstruct *Node) {
353       assert(DT.dominates(Node->Header, Node->Merge));
354       BlockSet OutsideBlocks;
355       OutsideBlocks.insert(Node->Merge);
356 
357       for (DivergentConstruct *It = Node->Parent; It != nullptr;
358            It = It->Parent) {
359         OutsideBlocks.insert(It->Merge);
360         if (It->Continue)
361           OutsideBlocks.insert(It->Continue);
362       }
363 
364       std::vector<BasicBlock *> Output;
365       partialOrderVisit(*Node->Header, [&](BasicBlock *BB) {
366         if (OutsideBlocks.count(BB) != 0)
367           return false;
368         if (DT.dominates(Node->Merge, BB) || !DT.dominates(Node->Header, BB))
369           return false;
370         Output.push_back(BB);
371         return true;
372       });
373       return Output;
374     }
375 
376     // Returns the list of blocks that belong to a SPIR-V switch construct.
377     std::vector<BasicBlock *> getSwitchConstructBlocks(BasicBlock *Header,
378                                                        BasicBlock *Merge) {
379       assert(DT.dominates(Header, Merge));
380 
381       std::vector<BasicBlock *> Output;
382       partialOrderVisit(*Header, [&](BasicBlock *BB) {
383         // the blocks structurally dominated by a switch header,
384         if (!DT.dominates(Header, BB))
385           return false;
386         // excluding blocks structurally dominated by the switch header’s merge
387         // block.
388         if (DT.dominates(Merge, BB) || BB == Merge)
389           return false;
390         Output.push_back(BB);
391         return true;
392       });
393       return Output;
394     }
395 
396     // Returns the list of blocks that belong to a SPIR-V case construct.
397     std::vector<BasicBlock *> getCaseConstructBlocks(BasicBlock *Target,
398                                                      BasicBlock *Merge) {
399       assert(DT.dominates(Target, Merge));
400 
401       std::vector<BasicBlock *> Output;
402       partialOrderVisit(*Target, [&](BasicBlock *BB) {
403         // the blocks structurally dominated by an OpSwitch Target or Default
404         // block
405         if (!DT.dominates(Target, BB))
406           return false;
407         // excluding the blocks structurally dominated by the OpSwitch
408         // construct’s corresponding merge block.
409         if (DT.dominates(Merge, BB) || BB == Merge)
410           return false;
411         Output.push_back(BB);
412         return true;
413       });
414       return Output;
415     }
416 
417     // Splits the given edges by recreating proxy nodes so that the destination
418     // has unique incoming edges from this region.
419     //
420     // clang-format off
421     //
422     // In SPIR-V, constructs must have a single exit/merge.
423     // Given nodes A and B in the construct, a node C outside, and the following edges.
424     //  A -> C
425     //  B -> C
426     //
427     // In such cases, we must create a new exit node D, that belong to the construct to make is viable:
428     // A -> D -> C
429     // B -> D -> C
430     //
431     // This is fine (assuming C has no PHI nodes), but requires handling the merge instruction here.
432     // By adding a proxy node, we create a regular divergent shape which can easily be regularized later on.
433     // A -> D -> D1 -> C
434     // B -> D -> D2 -> C
435     //
436     // A, B, D belongs to the construct. D is the exit. D1 and D2 are empty.
437     //
438     // clang-format on
439     std::vector<Edge>
440     createAliasBlocksForComplexEdges(std::vector<Edge> Edges) {
441       std::unordered_set<BasicBlock *> Seen;
442       std::vector<Edge> Output;
443       Output.reserve(Edges.size());
444 
445       for (auto &[Src, Dst] : Edges) {
446         auto [Iterator, Inserted] = Seen.insert(Src);
447         if (!Inserted) {
448           // Src already a source node. Cannot have 2 edges from A to B.
449           // Creating alias source block.
450           BasicBlock *NewSrc = BasicBlock::Create(
451               F.getContext(), Src->getName() + ".new.src", &F);
452           replaceBranchTargets(Src, Dst, NewSrc);
453           IRBuilder<> Builder(NewSrc);
454           Builder.CreateBr(Dst);
455           Src = NewSrc;
456         }
457 
458         Output.emplace_back(Src, Dst);
459       }
460 
461       return Output;
462     }
463 
464     AllocaInst *CreateVariable(Function &F, Type *Type,
465                                BasicBlock::iterator Position) {
466       const DataLayout &DL = F.getDataLayout();
467       return new AllocaInst(Type, DL.getAllocaAddrSpace(), nullptr, "reg",
468                             Position);
469     }
470 
471     // Given a construct defined by |Header|, and a list of exiting edges
472     // |Edges|, creates a new single exit node, fixing up those edges.
473     BasicBlock *createSingleExitNode(BasicBlock *Header,
474                                      std::vector<Edge> &Edges) {
475 
476       std::vector<Edge> FixedEdges = createAliasBlocksForComplexEdges(Edges);
477 
478       std::vector<BasicBlock *> Dsts;
479       std::unordered_map<BasicBlock *, ConstantInt *> DstToIndex;
480       auto NewExit = BasicBlock::Create(F.getContext(),
481                                         Header->getName() + ".new.exit", &F);
482       IRBuilder<> ExitBuilder(NewExit);
483       for (auto &[Src, Dst] : FixedEdges) {
484         if (DstToIndex.count(Dst) != 0)
485           continue;
486         DstToIndex.emplace(Dst, ExitBuilder.getInt32(DstToIndex.size()));
487         Dsts.push_back(Dst);
488       }
489 
490       if (Dsts.size() == 1) {
491         for (auto &[Src, Dst] : FixedEdges) {
492           replaceBranchTargets(Src, Dst, NewExit);
493         }
494         ExitBuilder.CreateBr(Dsts[0]);
495         return NewExit;
496       }
497 
498       AllocaInst *Variable = CreateVariable(F, ExitBuilder.getInt32Ty(),
499                                             F.begin()->getFirstInsertionPt());
500       for (auto &[Src, Dst] : FixedEdges) {
501         IRBuilder<> B2(Src);
502         B2.SetInsertPoint(Src->getFirstInsertionPt());
503         B2.CreateStore(DstToIndex[Dst], Variable);
504         replaceBranchTargets(Src, Dst, NewExit);
505       }
506 
507       llvm::Value *Load =
508           ExitBuilder.CreateLoad(ExitBuilder.getInt32Ty(), Variable);
509 
510       // If we can avoid an OpSwitch, generate an OpBranch. Reason is some
511       // OpBranch are allowed to exist without a new OpSelectionMerge if one of
512       // the branch is the parent's merge node, while OpSwitches are not.
513       if (Dsts.size() == 2) {
514         Value *Condition =
515             ExitBuilder.CreateCmp(CmpInst::ICMP_EQ, DstToIndex[Dsts[0]], Load);
516         ExitBuilder.CreateCondBr(Condition, Dsts[0], Dsts[1]);
517         return NewExit;
518       }
519 
520       SwitchInst *Sw = ExitBuilder.CreateSwitch(Load, Dsts[0], Dsts.size() - 1);
521       for (auto It = Dsts.begin() + 1; It != Dsts.end(); ++It) {
522         Sw->addCase(DstToIndex[*It], *It);
523       }
524       return NewExit;
525     }
526   };
527 
528   /// Create a value in BB set to the value associated with the branch the block
529   /// terminator will take.
530   Value *createExitVariable(
531       BasicBlock *BB,
532       const DenseMap<BasicBlock *, ConstantInt *> &TargetToValue) {
533     auto *T = BB->getTerminator();
534     if (isa<ReturnInst>(T))
535       return nullptr;
536 
537     IRBuilder<> Builder(BB);
538     Builder.SetInsertPoint(T);
539 
540     if (auto *BI = dyn_cast<BranchInst>(T)) {
541 
542       BasicBlock *LHSTarget = BI->getSuccessor(0);
543       BasicBlock *RHSTarget =
544           BI->isConditional() ? BI->getSuccessor(1) : nullptr;
545 
546       Value *LHS = TargetToValue.count(LHSTarget) != 0
547                        ? TargetToValue.at(LHSTarget)
548                        : nullptr;
549       Value *RHS = TargetToValue.count(RHSTarget) != 0
550                        ? TargetToValue.at(RHSTarget)
551                        : nullptr;
552 
553       if (LHS == nullptr || RHS == nullptr)
554         return LHS == nullptr ? RHS : LHS;
555       return Builder.CreateSelect(BI->getCondition(), LHS, RHS);
556     }
557 
558     // TODO: add support for switch cases.
559     llvm_unreachable("Unhandled terminator type.");
560   }
561 
562   // Creates a new basic block in F with a single OpUnreachable instruction.
563   BasicBlock *CreateUnreachable(Function &F) {
564     BasicBlock *BB = BasicBlock::Create(F.getContext(), "unreachable", &F);
565     IRBuilder<> Builder(BB);
566     Builder.CreateUnreachable();
567     return BB;
568   }
569 
570   // Add OpLoopMerge instruction on cycles.
571   bool addMergeForLoops(Function &F) {
572     LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
573     auto *TopLevelRegion =
574         getAnalysis<SPIRVConvergenceRegionAnalysisWrapperPass>()
575             .getRegionInfo()
576             .getTopLevelRegion();
577 
578     bool Modified = false;
579     for (auto &BB : F) {
580       // Not a loop header. Ignoring for now.
581       if (!LI.isLoopHeader(&BB))
582         continue;
583       auto *L = LI.getLoopFor(&BB);
584 
585       // This loop header is not the entrance of a convergence region. Ignoring
586       // this block.
587       auto *CR = getRegionForHeader(TopLevelRegion, &BB);
588       if (CR == nullptr)
589         continue;
590 
591       IRBuilder<> Builder(&BB);
592 
593       auto *Merge = getExitFor(CR);
594       // We are indeed in a loop, but there are no exits (infinite loop).
595       // This could be caused by a bad shader, but also could be an artifact
596       // from an earlier optimization. It is not always clear if structurally
597       // reachable means runtime reachable, so we cannot error-out. What we must
598       // do however is to make is legal on the SPIR-V point of view, hence
599       // adding an unreachable merge block.
600       if (Merge == nullptr) {
601         BranchInst *Br = cast<BranchInst>(BB.getTerminator());
602         assert(Br &&
603                "This assumes the branch is not a switch. Maybe that's wrong?");
604         assert(cast<BranchInst>(BB.getTerminator())->isUnconditional());
605 
606         Merge = CreateUnreachable(F);
607         Builder.SetInsertPoint(Br);
608         Builder.CreateCondBr(Builder.getFalse(), Merge, Br->getSuccessor(0));
609         Br->eraseFromParent();
610       }
611 
612       auto *Continue = L->getLoopLatch();
613 
614       Builder.SetInsertPoint(BB.getTerminator());
615       auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
616       auto ContinueAddress = BlockAddress::get(Continue->getParent(), Continue);
617       SmallVector<Value *, 2> Args = {MergeAddress, ContinueAddress};
618 
619       Builder.CreateIntrinsic(Intrinsic::spv_loop_merge, {}, {Args});
620       Modified = true;
621     }
622 
623     return Modified;
624   }
625 
626   // Adds an OpSelectionMerge to the immediate dominator or each node with an
627   // in-degree of 2 or more which is not already the merge target of an
628   // OpLoopMerge/OpSelectionMerge.
629   bool addMergeForNodesWithMultiplePredecessors(Function &F) {
630     DomTreeBuilder::BBDomTree DT;
631     DT.recalculate(F);
632 
633     bool Modified = false;
634     for (auto &BB : F) {
635       if (pred_size(&BB) <= 1)
636         continue;
637 
638       if (hasLoopMergeInstruction(BB) && pred_size(&BB) <= 2)
639         continue;
640 
641       assert(DT.getNode(&BB)->getIDom());
642       BasicBlock *Header = DT.getNode(&BB)->getIDom()->getBlock();
643 
644       if (isDefinedAsSelectionMergeBy(*Header, BB))
645         continue;
646 
647       IRBuilder<> Builder(Header);
648       Builder.SetInsertPoint(Header->getTerminator());
649 
650       auto MergeAddress = BlockAddress::get(BB.getParent(), &BB);
651       createOpSelectMerge(&Builder, MergeAddress);
652 
653       Modified = true;
654     }
655 
656     return Modified;
657   }
658 
659   // When a block has multiple OpSelectionMerge/OpLoopMerge instructions, sorts
660   // them to put the "largest" first. A merge instruction is defined as larger
661   // than another when its target merge block post-dominates the other target's
662   // merge block. (This ordering should match the nesting ordering of the source
663   // HLSL).
664   bool sortSelectionMerge(Function &F, BasicBlock &Block) {
665     std::vector<Instruction *> MergeInstructions;
666     for (Instruction &I : Block)
667       if (isMergeInstruction(&I))
668         MergeInstructions.push_back(&I);
669 
670     if (MergeInstructions.size() <= 1)
671       return false;
672 
673     Instruction *InsertionPoint = *MergeInstructions.begin();
674 
675     PartialOrderingVisitor Visitor(F);
676     std::sort(MergeInstructions.begin(), MergeInstructions.end(),
677               [&Visitor](Instruction *Left, Instruction *Right) {
678                 if (Left == Right)
679                   return false;
680                 BasicBlock *RightMerge = getDesignatedMergeBlock(Right);
681                 BasicBlock *LeftMerge = getDesignatedMergeBlock(Left);
682                 return !Visitor.compare(RightMerge, LeftMerge);
683               });
684 
685     for (Instruction *I : MergeInstructions) {
686       I->moveBefore(InsertionPoint->getIterator());
687       InsertionPoint = I;
688     }
689 
690     return true;
691   }
692 
693   // Sorts selection merge headers in |F|.
694   // A is sorted before B if the merge block designated by B is an ancestor of
695   // the one designated by A.
696   bool sortSelectionMergeHeaders(Function &F) {
697     bool Modified = false;
698     for (BasicBlock &BB : F) {
699       Modified |= sortSelectionMerge(F, BB);
700     }
701     return Modified;
702   }
703 
704   // Split basic blocks containing multiple OpLoopMerge/OpSelectionMerge
705   // instructions so each basic block contains only a single merge instruction.
706   bool splitBlocksWithMultipleHeaders(Function &F) {
707     std::stack<BasicBlock *> Work;
708     for (auto &BB : F) {
709       std::vector<Instruction *> MergeInstructions = getMergeInstructions(BB);
710       if (MergeInstructions.size() <= 1)
711         continue;
712       Work.push(&BB);
713     }
714 
715     const bool Modified = Work.size() > 0;
716     while (Work.size() > 0) {
717       BasicBlock *Header = Work.top();
718       Work.pop();
719 
720       std::vector<Instruction *> MergeInstructions =
721           getMergeInstructions(*Header);
722       for (unsigned i = 1; i < MergeInstructions.size(); i++) {
723         BasicBlock *NewBlock =
724             Header->splitBasicBlock(MergeInstructions[i], "new.header");
725 
726         if (getDesignatedContinueBlock(MergeInstructions[0]) == nullptr) {
727           BasicBlock *Unreachable = CreateUnreachable(F);
728 
729           BranchInst *BI = cast<BranchInst>(Header->getTerminator());
730           IRBuilder<> Builder(Header);
731           Builder.SetInsertPoint(BI);
732           Builder.CreateCondBr(Builder.getTrue(), NewBlock, Unreachable);
733           BI->eraseFromParent();
734         }
735 
736         Header = NewBlock;
737       }
738     }
739 
740     return Modified;
741   }
742 
743   // Adds an OpSelectionMerge to each block with an out-degree >= 2 which
744   // doesn't already have an OpSelectionMerge.
745   bool addMergeForDivergentBlocks(Function &F) {
746     DomTreeBuilder::BBPostDomTree PDT;
747     PDT.recalculate(F);
748     bool Modified = false;
749 
750     auto MergeBlocks = getMergeBlocks(F);
751     auto ContinueBlocks = getContinueBlocks(F);
752 
753     for (auto &BB : F) {
754       if (getMergeInstructions(BB).size() != 0)
755         continue;
756 
757       std::vector<BasicBlock *> Candidates;
758       for (BasicBlock *Successor : successors(&BB)) {
759         if (MergeBlocks.contains(Successor))
760           continue;
761         if (ContinueBlocks.contains(Successor))
762           continue;
763         Candidates.push_back(Successor);
764       }
765 
766       if (Candidates.size() <= 1)
767         continue;
768 
769       Modified = true;
770       BasicBlock *Merge = Candidates[0];
771 
772       auto MergeAddress = BlockAddress::get(Merge->getParent(), Merge);
773       IRBuilder<> Builder(&BB);
774       Builder.SetInsertPoint(BB.getTerminator());
775       createOpSelectMerge(&Builder, MergeAddress);
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 
790       for (BasicBlock *Successor : successors(Item)) {
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 
1034       BasicBlock *Successor = BB.getUniqueSuccessor();
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 
1055     DomTreeBuilder::BBDomTree DT;
1056     DomTreeBuilder::BBPostDomTree PDT;
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         createOpSelectMerge(&Builder, MergeAddress);
1109         continue;
1110       }
1111 
1112       Instruction *SplitInstruction = Merge->getTerminator();
1113       if (isMergeInstruction(SplitInstruction->getPrevNode()))
1114         SplitInstruction = SplitInstruction->getPrevNode();
1115       BasicBlock *NewMerge =
1116           Merge->splitBasicBlockBefore(SplitInstruction, "new.merge");
1117 
1118       IRBuilder<> Builder(Header);
1119       Builder.SetInsertPoint(Header->getTerminator());
1120 
1121       auto MergeAddress = BlockAddress::get(NewMerge->getParent(), NewMerge);
1122       createOpSelectMerge(&Builder, MergeAddress);
1123     }
1124 
1125     return Modified;
1126   }
1127 
1128 public:
1129   static char ID;
1130 
1131   SPIRVStructurizer() : FunctionPass(ID) {
1132     initializeSPIRVStructurizerPass(*PassRegistry::getPassRegistry());
1133   };
1134 
1135   virtual bool runOnFunction(Function &F) override {
1136     bool Modified = false;
1137 
1138     // In LLVM, Switches are allowed to have several cases branching to the same
1139     // basic block. This is allowed in SPIR-V, but can make structurizing SPIR-V
1140     // harder, so first remove edge cases.
1141     Modified |= splitSwitchCases(F);
1142 
1143     // LLVM allows conditional branches to have both side jumping to the same
1144     // block. It also allows switched to have a single default, or just one
1145     // case. Cleaning this up now.
1146     Modified |= simplifyBranches(F);
1147 
1148     // At this state, we should have a reducible CFG with cycles.
1149     // STEP 1: Adding OpLoopMerge instructions to loop headers.
1150     Modified |= addMergeForLoops(F);
1151 
1152     // STEP 2: adding OpSelectionMerge to each node with an in-degree >= 2.
1153     Modified |= addMergeForNodesWithMultiplePredecessors(F);
1154 
1155     // STEP 3:
1156     // Sort selection merge, the largest construct goes first.
1157     // This simplifies the next step.
1158     Modified |= sortSelectionMergeHeaders(F);
1159 
1160     // STEP 4: As this stage, we can have a single basic block with multiple
1161     // OpLoopMerge/OpSelectionMerge instructions. Splitting this block so each
1162     // BB has a single merge instruction.
1163     Modified |= splitBlocksWithMultipleHeaders(F);
1164 
1165     // STEP 5: In the previous steps, we added merge blocks the loops and
1166     // natural merge blocks (in-degree >= 2). What remains are conditions with
1167     // an exiting branch (return, unreachable). In such case, we must start from
1168     // the header, and add headers to divergent construct with no headers.
1169     Modified |= addMergeForDivergentBlocks(F);
1170 
1171     // STEP 6: At this stage, we have several divergent construct defines by a
1172     // header and a merge block. But their boundaries have no constraints: a
1173     // construct exit could be outside of the parents' construct exit. Such
1174     // edges are called critical edges. What we need is to split those edges
1175     // into several parts. Each part exiting the parent's construct by its merge
1176     // block.
1177     Modified |= splitCriticalEdges(F);
1178 
1179     // STEP 7: The previous steps possibly created a lot of "proxy" blocks.
1180     // Blocks with a single unconditional branch, used to create a valid
1181     // divergent construct tree. Some nodes are still requires (e.g: nodes
1182     // allowing a valid exit through the parent's merge block). But some are
1183     // left-overs of past transformations, and could cause actual validation
1184     // issues. E.g: the SPIR-V spec allows a construct to break to the parents
1185     // loop construct without an OpSelectionMerge, but this requires a straight
1186     // jump. If a proxy block lies between the conditional branch and the
1187     // parent's merge, the CFG is not valid.
1188     Modified |= removeUselessBlocks(F);
1189 
1190     // STEP 8: Final fix-up steps: our tree boundaries are correct, but some
1191     // blocks are branching with no header. Those are often simple conditional
1192     // branches with 1 or 2 returning edges. Adding a header for those.
1193     Modified |= addHeaderToRemainingDivergentDAG(F);
1194 
1195     // STEP 9: sort basic blocks to match both the LLVM & SPIR-V requirements.
1196     Modified |= sortBlocks(F);
1197 
1198     return Modified;
1199   }
1200 
1201   void getAnalysisUsage(AnalysisUsage &AU) const override {
1202     AU.addRequired<DominatorTreeWrapperPass>();
1203     AU.addRequired<LoopInfoWrapperPass>();
1204     AU.addRequired<SPIRVConvergenceRegionAnalysisWrapperPass>();
1205 
1206     AU.addPreserved<SPIRVConvergenceRegionAnalysisWrapperPass>();
1207     FunctionPass::getAnalysisUsage(AU);
1208   }
1209 
1210   void createOpSelectMerge(IRBuilder<> *Builder, BlockAddress *MergeAddress) {
1211     Instruction *BBTerminatorInst = Builder->GetInsertBlock()->getTerminator();
1212 
1213     MDNode *MDNode = BBTerminatorInst->getMetadata("hlsl.controlflow.hint");
1214 
1215     ConstantInt *BranchHint = llvm::ConstantInt::get(Builder->getInt32Ty(), 0);
1216 
1217     if (MDNode) {
1218       assert(MDNode->getNumOperands() == 2 &&
1219              "invalid metadata hlsl.controlflow.hint");
1220       BranchHint = mdconst::extract<ConstantInt>(MDNode->getOperand(1));
1221 
1222       assert(BranchHint && "invalid metadata value for hlsl.controlflow.hint");
1223     }
1224 
1225     llvm::SmallVector<llvm::Value *, 2> Args = {MergeAddress, BranchHint};
1226 
1227     Builder->CreateIntrinsic(Intrinsic::spv_selection_merge,
1228                              {MergeAddress->getType()}, {Args});
1229   }
1230 };
1231 } // namespace llvm
1232 
1233 char SPIRVStructurizer::ID = 0;
1234 
1235 INITIALIZE_PASS_BEGIN(SPIRVStructurizer, "spirv-structurizer",
1236                       "structurize SPIRV", false, false)
1237 INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
1238 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
1239 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
1240 INITIALIZE_PASS_DEPENDENCY(SPIRVConvergenceRegionAnalysisWrapperPass)
1241 
1242 INITIALIZE_PASS_END(SPIRVStructurizer, "spirv-structurizer",
1243                     "structurize SPIRV", false, false)
1244 
1245 FunctionPass *llvm::createSPIRVStructurizerPass() {
1246   return new SPIRVStructurizer();
1247 }
1248 
1249 PreservedAnalyses SPIRVStructurizerWrapper::run(Function &F,
1250                                                 FunctionAnalysisManager &AF) {
1251 
1252   auto FPM = legacy::FunctionPassManager(F.getParent());
1253   FPM.add(createSPIRVStructurizerPass());
1254 
1255   if (!FPM.run(F))
1256     return PreservedAnalyses::all();
1257   PreservedAnalyses PA;
1258   PA.preserveSet<CFGAnalyses>();
1259   return PA;
1260 }
1261