1//===- StructurizeCFG.cpp -------------------------------------------------===//
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#include "llvm/Transforms/Scalar/StructurizeCFG.h"
10#include "ScalarOptions.h"
11#include "llvm/ADT/DenseMap.h"
12#include "llvm/ADT/EquivalenceClasses.h"
13#include "llvm/ADT/MapVector.h"
14#include "llvm/ADT/SCCIterator.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallPtrSet.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/Analysis/InstructionSimplify.h"
19#include "llvm/Analysis/RegionInfo.h"
20#include "llvm/Analysis/RegionIterator.h"
21#include "llvm/Analysis/RegionPass.h"
22#include "llvm/Analysis/TargetTransformInfo.h"
23#include "llvm/Analysis/UniformityAnalysis.h"
24#include "llvm/IR/BasicBlock.h"
25#include "llvm/IR/CFG.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/Dominators.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/InstrTypes.h"
30#include "llvm/IR/Instruction.h"
31#include "llvm/IR/Instructions.h"
32#include "llvm/IR/Metadata.h"
33#include "llvm/IR/PassManager.h"
34#include "llvm/IR/PatternMatch.h"
35#include "llvm/IR/ProfDataUtils.h"
36#include "llvm/IR/Type.h"
37#include "llvm/IR/Use.h"
38#include "llvm/IR/Value.h"
39#include "llvm/IR/ValueHandle.h"
40#include "llvm/InitializePasses.h"
41#include "llvm/Pass.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/Debug.h"
44#include "llvm/Support/raw_ostream.h"
45#include "llvm/Transforms/Scalar.h"
46#include "llvm/Transforms/Utils.h"
47#include "llvm/Transforms/Utils/BasicBlockUtils.h"
48#include "llvm/Transforms/Utils/Local.h"
49#include "llvm/Transforms/Utils/SSAUpdater.h"
50#include "llvm/Transforms/Utils/SSAUpdaterBulk.h"
51#include <cassert>
52#include <utility>
53
54using namespace llvm;
55using namespace llvm::PatternMatch;
56
57#define DEBUG_TYPE "structurizecfg"
58
59// The name for newly created blocks.
60const char FlowBlockName[] = "Flow";
61
62namespace {
63
64// Definition of the complex types used in this pass.
65
66using BBValuePair = std::pair<BasicBlock *, Value *>;
67
68using RNVector = SmallVector<RegionNode *, 8>;
69using BBVector = SmallVector<BasicBlock *, 8>;
70using BranchVector = SmallVector<CondBrInst *, 8>;
71using BBValueVector = SmallVector<BBValuePair, 2>;
72
73using BBSet = SmallPtrSet<BasicBlock *, 8>;
74
75using PhiMap = MapVector<PHINode *, BBValueVector>;
76using BB2BBVecMap = MapVector<BasicBlock *, BBVector>;
77
78using BBPhiMap = DenseMap<BasicBlock *, PhiMap>;
79
80using MaybeCondBranchWeights = std::optional<class CondBranchWeights>;
81
82class CondBranchWeights {
83 uint32_t TrueWeight;
84 uint32_t FalseWeight;
85
86 CondBranchWeights(uint32_t T, uint32_t F) : TrueWeight(T), FalseWeight(F) {}
87
88public:
89 static MaybeCondBranchWeights tryParse(const CondBrInst &Br) {
90 uint64_t T, F;
91 if (!extractBranchWeights(I: Br, TrueVal&: T, FalseVal&: F))
92 return std::nullopt;
93
94 return CondBranchWeights(T, F);
95 }
96
97 static void setMetadata(CondBrInst &Br,
98 const MaybeCondBranchWeights &Weights) {
99 if (!Weights)
100 return;
101 uint32_t Arr[] = {Weights->TrueWeight, Weights->FalseWeight};
102 setBranchWeights(I&: Br, Weights: Arr, IsExpected: false);
103 }
104
105 CondBranchWeights invert() const {
106 return CondBranchWeights{FalseWeight, TrueWeight};
107 }
108};
109
110struct PredInfo {
111 Value *Pred;
112 MaybeCondBranchWeights Weights;
113};
114
115using BBPredicates = DenseMap<BasicBlock *, PredInfo>;
116using PredMap = DenseMap<BasicBlock *, BBPredicates>;
117using BB2BBMap = DenseMap<BasicBlock *, BasicBlock *>;
118using Val2BBMap = DenseMap<Value *, BasicBlock *>;
119
120// A traits type that is intended to be used in graph algorithms. The graph
121// traits starts at an entry node, and traverses the RegionNodes that are in
122// the Nodes set.
123struct SubGraphTraits {
124 using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>;
125 using BaseSuccIterator = GraphTraits<RegionNode *>::ChildIteratorType;
126
127 // This wraps a set of Nodes into the iterator, so we know which edges to
128 // filter out.
129 class WrappedSuccIterator
130 : public iterator_adaptor_base<
131 WrappedSuccIterator, BaseSuccIterator,
132 std::iterator_traits<BaseSuccIterator>::iterator_category, NodeRef,
133 std::ptrdiff_t, NodeRef *, NodeRef> {
134 SmallDenseSet<RegionNode *> *Nodes;
135
136 public:
137 WrappedSuccIterator(BaseSuccIterator It, SmallDenseSet<RegionNode *> *Nodes)
138 : iterator_adaptor_base(It), Nodes(Nodes) {}
139
140 NodeRef operator*() const { return {*I, Nodes}; }
141 };
142
143 static bool filterAll(const NodeRef &N) { return true; }
144 static bool filterSet(const NodeRef &N) { return N.second->count(V: N.first); }
145
146 using ChildIteratorType =
147 filter_iterator<WrappedSuccIterator, bool (*)(const NodeRef &)>;
148
149 static NodeRef getEntryNode(Region *R) {
150 return {GraphTraits<Region *>::getEntryNode(R), nullptr};
151 }
152
153 static NodeRef getEntryNode(NodeRef N) { return N; }
154
155 static iterator_range<ChildIteratorType> children(const NodeRef &N) {
156 auto *filter = N.second ? &filterSet : &filterAll;
157 return make_filter_range(
158 Range: make_range<WrappedSuccIterator>(
159 x: {GraphTraits<RegionNode *>::child_begin(N: N.first), N.second},
160 y: {GraphTraits<RegionNode *>::child_end(N: N.first), N.second}),
161 Pred: filter);
162 }
163
164 static ChildIteratorType child_begin(const NodeRef &N) {
165 return children(N).begin();
166 }
167
168 static ChildIteratorType child_end(const NodeRef &N) {
169 return children(N).end();
170 }
171};
172
173/// Finds the nearest common dominator of a set of BasicBlocks.
174///
175/// For every BB you add to the set, you can specify whether we "remember" the
176/// block. When you get the common dominator, you can also ask whether it's one
177/// of the blocks we remembered.
178class NearestCommonDominator {
179 DominatorTree *DT;
180 BasicBlock *Result = nullptr;
181 bool ResultIsRemembered = false;
182
183 /// Add BB to the resulting dominator.
184 void addBlock(BasicBlock *BB, bool Remember) {
185 if (!Result) {
186 Result = BB;
187 ResultIsRemembered = Remember;
188 return;
189 }
190
191 BasicBlock *NewResult = DT->findNearestCommonDominator(A: Result, B: BB);
192 if (NewResult != Result)
193 ResultIsRemembered = false;
194 if (NewResult == BB)
195 ResultIsRemembered |= Remember;
196 Result = NewResult;
197 }
198
199public:
200 explicit NearestCommonDominator(DominatorTree *DomTree) : DT(DomTree) {}
201
202 void addBlock(BasicBlock *BB) {
203 addBlock(BB, /* Remember = */ false);
204 }
205
206 void addAndRememberBlock(BasicBlock *BB) {
207 addBlock(BB, /* Remember = */ true);
208 }
209
210 /// Get the nearest common dominator of all the BBs added via addBlock() and
211 /// addAndRememberBlock().
212 BasicBlock *result() { return Result; }
213
214 /// Is the BB returned by getResult() one of the blocks we added to the set
215 /// with addAndRememberBlock()?
216 bool resultIsRememberedBlock() { return ResultIsRemembered; }
217};
218
219/// Transforms the control flow graph on one single entry/exit region
220/// at a time.
221///
222/// After the transform all "If"/"Then"/"Else" style control flow looks like
223/// this:
224///
225/// \verbatim
226/// 1
227/// ||
228/// | |
229/// 2 |
230/// | /
231/// |/
232/// 3
233/// || Where:
234/// | | 1 = "If" block, calculates the condition
235/// 4 | 2 = "Then" subregion, runs if the condition is true
236/// | / 3 = "Flow" blocks, newly inserted flow blocks, rejoins the flow
237/// |/ 4 = "Else" optional subregion, runs if the condition is false
238/// 5 5 = "End" block, also rejoins the control flow
239/// \endverbatim
240///
241/// Control flow is expressed as a branch where the true exit goes into the
242/// "Then"/"Else" region, while the false exit skips the region
243/// The condition for the optional "Else" region is expressed as a PHI node.
244/// The incoming values of the PHI node are true for the "If" edge and false
245/// for the "Then" edge.
246///
247/// Additionally to that even complicated loops look like this:
248///
249/// \verbatim
250/// 1
251/// ||
252/// | |
253/// 2 ^ Where:
254/// | / 1 = "Entry" block
255/// |/ 2 = "Loop" optional subregion, with all exits at "Flow" block
256/// 3 3 = "Flow" block, with back edge to entry block
257/// |
258/// \endverbatim
259///
260/// The back edge of the "Flow" block is always on the false side of the branch
261/// while the true side continues the general flow. So the loop condition
262/// consist of a network of PHI nodes where the true incoming values expresses
263/// breaks and the false values expresses continue states.
264
265class StructurizeCFG {
266 Type *Boolean;
267 ConstantInt *BoolTrue;
268 ConstantInt *BoolFalse;
269 Value *BoolPoison;
270 const TargetTransformInfo *TTI;
271 Function *Func;
272 Region *ParentRegion;
273
274 UniformityInfo *UA = nullptr;
275 DominatorTree *DT;
276
277 SmallVector<RegionNode *, 8> Order;
278 BBSet Visited;
279 BBSet FlowSet;
280
281 SmallVector<WeakVH, 8> AffectedPhis;
282 BBPhiMap DeletedPhis;
283 BB2BBVecMap AddedPhis;
284
285 PredMap Predicates;
286 BranchVector Conditions;
287
288 BB2BBMap Loops;
289 PredMap LoopPreds;
290 BranchVector LoopConds;
291
292 Val2BBMap HoistedValues;
293
294 RegionNode *PrevNode;
295
296 void hoistZeroCostElseBlockPhiValues(BasicBlock *ElseBB, BasicBlock *ThenBB);
297
298 bool isHoistableInstruction(Instruction *I, BasicBlock *BB,
299 BasicBlock *HoistTo);
300
301 void orderNodes();
302
303 void analyzeLoops(RegionNode *N);
304
305 PredInfo buildCondition(CondBrInst *Term, unsigned Idx, bool Invert);
306
307 void gatherPredicates(RegionNode *N);
308
309 void collectInfos();
310
311 void insertConditions(bool Loops, SSAUpdaterBulk &PhiInserter);
312
313 void simplifyConditions();
314
315 void delPhiValues(BasicBlock *From, BasicBlock *To);
316
317 void addPhiValues(BasicBlock *From, BasicBlock *To);
318
319 void findUndefBlocks(BasicBlock *PHIBlock,
320 const SmallPtrSet<BasicBlock *, 8> &Incomings,
321 SmallVector<BasicBlock *> &UndefBlks) const;
322
323 void mergeIfCompatible(EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A,
324 PHINode *B);
325
326 void setPhiValues();
327
328 void simplifyAffectedPhis();
329
330 void simplifyHoistedPhis();
331
332 DebugLoc killTerminator(BasicBlock *BB);
333
334 void changeExit(RegionNode *Node, BasicBlock *NewExit,
335 bool IncludeDominator);
336
337 BasicBlock *getNextFlow(BasicBlock *Dominator);
338
339 std::pair<BasicBlock *, DebugLoc> needPrefix(bool NeedEmpty);
340
341 BasicBlock *needPostfix(BasicBlock *Flow, bool ExitUseAllowed);
342
343 void setPrevNode(BasicBlock *BB);
344
345 bool dominatesPredicates(BasicBlock *BB, RegionNode *Node);
346
347 bool isPredictableTrue(RegionNode *Node);
348
349 void wireFlow(bool ExitUseAllowed, BasicBlock *LoopEnd);
350
351 void handleLoops(bool ExitUseAllowed, BasicBlock *LoopEnd);
352
353 void createFlow();
354
355 void rebuildSSA();
356
357public:
358 void init(Region *R);
359 bool run(Region *R, DominatorTree *DT, const TargetTransformInfo *TTI);
360 bool makeUniformRegion(Region *R, UniformityInfo &UA);
361};
362
363class StructurizeCFGLegacyPass : public RegionPass {
364 bool SkipUniformRegions;
365
366public:
367 static char ID;
368
369 explicit StructurizeCFGLegacyPass(bool SkipUniformRegions_ = false)
370 : RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) {
371 initializeStructurizeCFGLegacyPassPass(*PassRegistry::getPassRegistry());
372 }
373
374 bool runOnRegion(Region *R, RGPassManager &RGM) override {
375 StructurizeCFG SCFG;
376 SCFG.init(R);
377 const ScalarOptions &Opts =
378 R->getEntry()->getContext().getLibraryOptions().get<ScalarOptions>();
379 if (valueOr(X: Opts.structurizecfg_skip_uniform_regions, Default: SkipUniformRegions)) {
380 UniformityInfo &UA =
381 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
382 if (SCFG.makeUniformRegion(R, UA))
383 return false;
384 }
385 Function *F = R->getEntry()->getParent();
386 const TargetTransformInfo *TTI =
387 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F: *F);
388 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
389 return SCFG.run(R, DT, TTI);
390 }
391
392 StringRef getPassName() const override { return "Structurize control flow"; }
393
394 void getAnalysisUsage(AnalysisUsage &AU) const override {
395 AU.addRequired<UniformityInfoWrapperPass>();
396 AU.addRequired<DominatorTreeWrapperPass>();
397 AU.addRequired<TargetTransformInfoWrapperPass>();
398
399 AU.addPreserved<DominatorTreeWrapperPass>();
400 RegionPass::getAnalysisUsage(AU);
401 }
402};
403
404} // end anonymous namespace
405
406char StructurizeCFGLegacyPass::ID = 0;
407
408INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg",
409 "Structurize the CFG", false, false)
410INITIALIZE_PASS_DEPENDENCY(UniformityInfoWrapperPass)
411INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
412INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
413INITIALIZE_PASS_DEPENDENCY(RegionInfoPass)
414INITIALIZE_PASS_END(StructurizeCFGLegacyPass, "structurizecfg",
415 "Structurize the CFG", false, false)
416
417/// Checks whether an instruction is zero cost instruction and checks if the
418/// operands are from different BB. If so, this instruction can be coalesced
419/// if its hoisted to predecessor block. So, this returns true.
420bool StructurizeCFG::isHoistableInstruction(Instruction *I, BasicBlock *BB,
421 BasicBlock *HoistTo) {
422 if (I->getParent() != BB || isa<PHINode>(Val: I))
423 return false;
424
425 // If the instruction is not a zero cost instruction, return false.
426 auto Cost = TTI->getInstructionCost(U: I, CostKind: TargetTransformInfo::TCK_Latency);
427 InstructionCost::CostType CostVal =
428 Cost.isValid()
429 ? Cost.getValue()
430 : (InstructionCost::CostType)TargetTransformInfo::TCC_Expensive;
431 if (CostVal != 0)
432 return false;
433
434 // Check if all operands are available at the hoisting destination.
435 for (auto &Op : I->operands()) {
436 if (auto *OpI = dyn_cast<Instruction>(Val&: Op)) {
437 // Operand must dominate the hoisting destination.
438 if (!DT->dominates(A: OpI->getParent(), B: HoistTo))
439 return false;
440 }
441 }
442
443 return true;
444}
445
446/// Structurization can introduce unnecessary VGPR copies due to register
447/// coalescing interference. For example, if the Else block has a zero-cost
448/// instruction and the Then block modifies the VGPR value, only one value is
449/// live at a time in merge block before structurization. After structurization,
450/// the coalescer may incorrectly treat the Then value as live in the Else block
451/// (via the path Then → Flow → Else), leading to unnecessary VGPR copies.
452///
453/// This function examines phi nodes whose incoming values are zero-cost
454/// instructions in the Else block. It identifies such values that can be safely
455/// hoisted and moves them to the nearest common dominator of Then and Else
456/// blocks. A follow-up function after setting PhiNodes assigns the hoisted
457/// value to poison phi nodes along the if→flow edge, aiding register coalescing
458/// and minimizing unnecessary live ranges.
459void StructurizeCFG::hoistZeroCostElseBlockPhiValues(BasicBlock *ElseBB,
460 BasicBlock *ThenBB) {
461
462 BasicBlock *ElseSucc = ElseBB->getSingleSuccessor();
463 BasicBlock *CommonDominator = DT->findNearestCommonDominator(A: ElseBB, B: ThenBB);
464
465 if (!ElseSucc || !CommonDominator)
466 return;
467 // Only hoist in a simple if-else: ThenBB must branch directly to ElseSucc
468 // and ElseSucc must have exactly 2 predecessors (ThenBB and ElseBB).
469 // simplifyHoistedPhis assumes this exact shape; with additional predecessors
470 // the hoisted value leaks into unrelated control-flow paths.
471 if (ThenBB->getSingleSuccessor() != ElseSucc ||
472 !ElseSucc->hasNPredecessors(N: 2))
473 return;
474 Instruction *Term = CommonDominator->getTerminator();
475 for (PHINode &Phi : ElseSucc->phis()) {
476 Value *ElseVal = Phi.getIncomingValueForBlock(BB: ElseBB);
477 auto *Inst = dyn_cast<Instruction>(Val: ElseVal);
478 if (!Inst || !isHoistableInstruction(I: Inst, BB: ElseBB, HoistTo: CommonDominator))
479 continue;
480 Inst->removeFromParent();
481 Inst->insertInto(ParentBB: CommonDominator, It: Term->getIterator());
482 HoistedValues[Inst] = CommonDominator;
483 }
484}
485
486/// Build up the general order of nodes, by performing a topological sort of the
487/// parent region's nodes, while ensuring that there is no outer cycle node
488/// between any two inner cycle nodes.
489void StructurizeCFG::orderNodes() {
490 Order.resize(N: std::distance(first: GraphTraits<Region *>::nodes_begin(R: ParentRegion),
491 last: GraphTraits<Region *>::nodes_end(R: ParentRegion)));
492 if (Order.empty())
493 return;
494
495 SmallDenseSet<RegionNode *> Nodes;
496 auto EntryNode = SubGraphTraits::getEntryNode(R: ParentRegion);
497
498 // A list of range indices of SCCs in Order, to be processed.
499 SmallVector<std::pair<unsigned, unsigned>, 8> WorkList;
500 unsigned I = 0, E = Order.size();
501 while (true) {
502 // Run through all the SCCs in the subgraph starting with Entry.
503 for (auto SCCI =
504 scc_iterator<SubGraphTraits::NodeRef, SubGraphTraits>::begin(
505 G: EntryNode);
506 !SCCI.isAtEnd(); ++SCCI) {
507 auto &SCC = *SCCI;
508
509 // An SCC up to the size of 2, can be reduced to an entry (the last node),
510 // and a possible additional node. Therefore, it is already in order, and
511 // there is no need to add it to the work-list.
512 unsigned Size = SCC.size();
513 if (Size > 2)
514 WorkList.emplace_back(Args&: I, Args: I + Size);
515
516 // Add the SCC nodes to the Order array.
517 for (const auto &N : SCC) {
518 assert(I < E && "SCC size mismatch!");
519 Order[I++] = N.first;
520 }
521 }
522 assert(I == E && "SCC size mismatch!");
523
524 // If there are no more SCCs to order, then we are done.
525 if (WorkList.empty())
526 break;
527
528 std::tie(args&: I, args&: E) = WorkList.pop_back_val();
529
530 // Collect the set of nodes in the SCC's subgraph. These are only the
531 // possible child nodes; we do not add the entry (last node) otherwise we
532 // will have the same exact SCC all over again.
533 Nodes.clear();
534 Nodes.insert(I: Order.begin() + I, E: Order.begin() + E - 1);
535
536 // Update the entry node.
537 EntryNode.first = Order[E - 1];
538 EntryNode.second = &Nodes;
539 }
540}
541
542/// Determine the end of the loops
543void StructurizeCFG::analyzeLoops(RegionNode *N) {
544 if (N->isSubRegion()) {
545 // Test for exit as back edge
546 BasicBlock *Exit = N->getNodeAs<Region>()->getExit();
547 if (Visited.count(Ptr: Exit))
548 Loops[Exit] = N->getEntry();
549
550 } else {
551 // Test for successors as back edge
552 // TODO: support other terminators other than branches.
553 BasicBlock *BB = N->getNodeAs<BasicBlock>();
554 if (isa<UncondBrInst, CondBrInst>(Val: BB->getTerminator()))
555 for (BasicBlock *Succ : successors(BB))
556 if (Visited.count(Ptr: Succ))
557 Loops[Succ] = BB;
558 }
559}
560
561/// Build the condition for one edge
562PredInfo StructurizeCFG::buildCondition(CondBrInst *Term, unsigned Idx,
563 bool Invert) {
564 Value *Cond = Term->getCondition();
565 auto Weights = CondBranchWeights::tryParse(Br: *Term);
566 if (Idx != (unsigned)Invert) {
567 Cond = invertCondition(Condition: Cond);
568 if (Weights)
569 Weights = Weights->invert();
570 }
571 return {.Pred: Cond, .Weights: Weights};
572}
573
574/// Analyze the predecessors of each block and build up predicates
575void StructurizeCFG::gatherPredicates(RegionNode *N) {
576 RegionInfo *RI = ParentRegion->getRegionInfo();
577 BasicBlock *BB = N->getEntry();
578 BBPredicates &Pred = Predicates[BB];
579 BBPredicates &LPred = LoopPreds[BB];
580
581 for (BasicBlock *P : predecessors(BB)) {
582 // Ignore it if it's a branch from outside into our region entry
583 if (!ParentRegion->contains(BB: P))
584 continue;
585
586 Region *R = RI->getRegionFor(BB: P);
587 if (R == ParentRegion) {
588 if (isa<UncondBrInst>(Val: P->getTerminator())) {
589 if (Visited.count(Ptr: P))
590 Pred[P] = {.Pred: BoolTrue, .Weights: std::nullopt};
591 else
592 LPred[P] = {.Pred: BoolFalse, .Weights: std::nullopt};
593 } else if (auto *CondBr = dyn_cast<CondBrInst>(Val: P->getTerminator())) {
594 bool Idx = CondBr->getSuccessor(i: 0) == BB ? 0 : 1;
595 if (Visited.count(Ptr: P)) {
596 // Normal forward edge
597 // Try to treat Other like an ELSE block
598 BasicBlock *Other = CondBr->getSuccessor(i: !Idx);
599 if (Visited.count(Ptr: Other) && !Loops.count(Val: Other) &&
600 !Pred.count(Val: Other) && !Pred.count(Val: P)) {
601 hoistZeroCostElseBlockPhiValues(ElseBB: BB, ThenBB: Other);
602 Pred[Other] = {.Pred: BoolFalse, .Weights: std::nullopt};
603 Pred[P] = {.Pred: BoolTrue, .Weights: std::nullopt};
604 } else
605 Pred[P] = buildCondition(Term: CondBr, Idx, Invert: false);
606 } else {
607 // Back edge
608 LPred[P] = buildCondition(Term: CondBr, Idx, Invert: true);
609 }
610 }
611 } else {
612 // It's an exit from a sub region
613 while (R->getParent() != ParentRegion)
614 R = R->getParent();
615
616 // Edge from inside a subregion to its entry, ignore it
617 if (*R == *N)
618 continue;
619
620 BasicBlock *Entry = R->getEntry();
621 if (Visited.count(Ptr: Entry))
622 Pred[Entry] = {.Pred: BoolTrue, .Weights: std::nullopt};
623 else
624 LPred[Entry] = {.Pred: BoolFalse, .Weights: std::nullopt};
625 }
626 }
627}
628
629/// Collect various loop and predicate infos
630void StructurizeCFG::collectInfos() {
631 // Reset predicate
632 Predicates.clear();
633
634 // and loop infos
635 Loops.clear();
636 LoopPreds.clear();
637
638 // Reset the visited nodes
639 Visited.clear();
640
641 for (RegionNode *RN : reverse(C&: Order)) {
642 LLVM_DEBUG(dbgs() << "Visiting: "
643 << (RN->isSubRegion() ? "SubRegion with entry: " : "")
644 << RN->getEntry()->getName() << "\n");
645
646 // Analyze all the conditions leading to a node
647 gatherPredicates(N: RN);
648
649 // Remember that we've seen this node
650 Visited.insert(Ptr: RN->getEntry());
651
652 // Find the last back edges
653 analyzeLoops(N: RN);
654 }
655}
656
657/// Insert the missing branch conditions
658void StructurizeCFG::insertConditions(bool Loops, SSAUpdaterBulk &PhiInserter) {
659 BranchVector &Conds = Loops ? LoopConds : Conditions;
660 Value *Default = Loops ? BoolTrue : BoolFalse;
661
662 for (CondBrInst *Term : Conds) {
663 BasicBlock *Parent = Term->getParent();
664 BasicBlock *SuccTrue = Term->getSuccessor(i: 0);
665 BasicBlock *SuccFalse = Term->getSuccessor(i: 1);
666
667 unsigned Variable = PhiInserter.AddVariable(Name: "", Ty: Boolean);
668 PhiInserter.AddAvailableValue(Var: Variable, BB: Loops ? SuccFalse : Parent,
669 V: Default);
670
671 BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue];
672
673 NearestCommonDominator Dominator(DT);
674 Dominator.addBlock(BB: Parent);
675
676 PredInfo ParentInfo{.Pred: nullptr, .Weights: std::nullopt};
677 for (auto [BB, PI] : Preds) {
678 if (BB == Parent) {
679 ParentInfo = PI;
680 break;
681 }
682 PhiInserter.AddAvailableValue(Var: Variable, BB, V: PI.Pred);
683 Dominator.addAndRememberBlock(BB);
684 }
685
686 if (ParentInfo.Pred) {
687 Term->setCondition(ParentInfo.Pred);
688 CondBranchWeights::setMetadata(Br&: *Term, Weights: ParentInfo.Weights);
689 } else {
690 if (!Dominator.resultIsRememberedBlock())
691 PhiInserter.AddAvailableValue(Var: Variable, BB: Dominator.result(), V: Default);
692
693 PhiInserter.AddUse(Var: Variable, U: &Term->getOperandUse(i: 0));
694 }
695 }
696}
697
698/// Simplify any inverted conditions that were built by buildConditions.
699void StructurizeCFG::simplifyConditions() {
700 SmallVector<Instruction *> InstToErase;
701 for (auto &I : concat<PredMap::value_type>(Ranges&: Predicates, Ranges&: LoopPreds)) {
702 auto &Preds = I.second;
703 for (auto [BB, PI] : Preds) {
704 Instruction *Inverted;
705 if (match(V: PI.Pred, P: m_Not(V: m_OneUse(SubPattern: m_Instruction(I&: Inverted)))) &&
706 !PI.Pred->use_empty()) {
707 if (auto *InvertedCmp = dyn_cast<CmpInst>(Val: Inverted)) {
708 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
709 PI.Pred->replaceAllUsesWith(V: InvertedCmp);
710 InstToErase.push_back(Elt: cast<Instruction>(Val: PI.Pred));
711 }
712 }
713 }
714 }
715 for (auto *I : InstToErase)
716 I->eraseFromParent();
717}
718
719/// Remove all PHI values coming from "From" into "To" and remember
720/// them in DeletedPhis
721void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
722 PhiMap &Map = DeletedPhis[To];
723 for (PHINode &Phi : To->phis()) {
724 bool Recorded = false;
725 while (Phi.getBasicBlockIndex(BB: From) != -1) {
726 Value *Deleted = Phi.removeIncomingValue(BB: From, DeletePHIIfEmpty: false);
727 Map[&Phi].push_back(Elt: std::make_pair(x&: From, y&: Deleted));
728 if (!Recorded) {
729 AffectedPhis.push_back(Elt: &Phi);
730 Recorded = true;
731 }
732 }
733 }
734}
735
736/// Add a dummy PHI value as soon as we knew the new predecessor
737void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
738 for (PHINode &Phi : To->phis()) {
739 Value *Poison = PoisonValue::get(T: Phi.getType());
740 Phi.addIncoming(V: Poison, BB: From);
741 }
742 AddedPhis[To].push_back(Elt: From);
743}
744
745/// When we are reconstructing a PHI inside \p PHIBlock with incoming values
746/// from predecessors \p Incomings, we have a chance to mark the available value
747/// from some blocks as undefined. The function will find out all such blocks
748/// and return in \p UndefBlks.
749void StructurizeCFG::findUndefBlocks(
750 BasicBlock *PHIBlock, const SmallPtrSet<BasicBlock *, 8> &Incomings,
751 SmallVector<BasicBlock *> &UndefBlks) const {
752 // We may get a post-structured CFG like below:
753 //
754 // | P1
755 // |/
756 // F1
757 // |\
758 // | N
759 // |/
760 // F2
761 // |\
762 // | P2
763 // |/
764 // F3
765 // |\
766 // B
767 //
768 // B is the block that has a PHI being reconstructed. P1/P2 are predecessors
769 // of B before structurization. F1/F2/F3 are flow blocks inserted during
770 // structurization process. Block N is not a predecessor of B before
771 // structurization, but are placed between the predecessors(P1/P2) of B after
772 // structurization. This usually means that threads went to N never take the
773 // path N->F2->F3->B. For example, the threads take the branch F1->N may
774 // always take the branch F2->P2. So, when we are reconstructing a PHI
775 // originally in B, we can safely say the incoming value from N is undefined.
776 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
777 SmallVector<BasicBlock *, 8> Stack;
778 if (PHIBlock == ParentRegion->getExit()) {
779 for (auto P : predecessors(BB: PHIBlock)) {
780 if (ParentRegion->contains(BB: P))
781 Stack.push_back(Elt: P);
782 }
783 } else {
784 append_range(C&: Stack, R: predecessors(BB: PHIBlock));
785 }
786
787 // Do a backward traversal over the CFG, and stop further searching if
788 // the block is not a Flow. If a block is neither flow block nor the
789 // incoming predecessor, then the incoming value from the block is
790 // undefined value for the PHI being reconstructed.
791 while (!Stack.empty()) {
792 BasicBlock *Current = Stack.pop_back_val();
793 if (!VisitedBlock.insert(Ptr: Current).second)
794 continue;
795
796 if (FlowSet.contains(Ptr: Current))
797 llvm::append_range(C&: Stack, R: predecessors(BB: Current));
798 else if (!Incomings.contains(Ptr: Current))
799 UndefBlks.push_back(Elt: Current);
800 }
801}
802
803// If two phi nodes have compatible incoming values (for each
804// incoming block, either they have the same incoming value or only one phi
805// node has an incoming value), let them share the merged incoming values. The
806// merge process is guided by the equivalence information from \p PhiClasses.
807// The function will possibly update the incoming values of leader phi in
808// DeletedPhis.
809void StructurizeCFG::mergeIfCompatible(
810 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A, PHINode *B) {
811 auto ItA = PhiClasses.findLeader(ECV: PhiClasses.insert(Data: A));
812 auto ItB = PhiClasses.findLeader(ECV: PhiClasses.insert(Data: B));
813 // They are already in the same class, no work needed.
814 if (ItA == ItB)
815 return;
816
817 PHINode *LeaderA = *ItA;
818 PHINode *LeaderB = *ItB;
819 BBValueVector &IncomingA = DeletedPhis[LeaderA->getParent()][LeaderA];
820 BBValueVector &IncomingB = DeletedPhis[LeaderB->getParent()][LeaderB];
821
822 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
823 for (auto [BB, V] : IncomingB) {
824 auto BBIt = Mergeable.find(Val: BB);
825 if (BBIt != Mergeable.end() && BBIt->second != V)
826 return;
827 // Either IncomingA does not have this value or IncomingA has the same
828 // value.
829 Mergeable.insert(KV: {BB, V});
830 }
831
832 // Update the incoming value of leaderA.
833 IncomingA.assign(in_start: Mergeable.begin(), in_end: Mergeable.end());
834 PhiClasses.unionSets(L1: ItA, L2: ItB);
835}
836
837/// Add the real PHI value as soon as everything is set up
838void StructurizeCFG::setPhiValues() {
839 SmallVector<PHINode *, 8> InsertedPhis;
840 SSAUpdater Updater(&InsertedPhis);
841 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
842
843 // Find phi nodes that have compatible incoming values (either they have
844 // the same value for the same block or only one phi node has an incoming
845 // value, see example below). We only search again the phi's that are
846 // referenced by another phi, which is the case we care about.
847 //
848 // For example (-- means no incoming value):
849 // phi1 : BB1:phi2 BB2:v BB3:--
850 // phi2: BB1:-- BB2:v BB3:w
851 //
852 // Then we can merge these incoming values and let phi1, phi2 use the
853 // same set of incoming values:
854 //
855 // phi1&phi2: BB1:phi2 BB2:v BB3:w
856 //
857 // By doing this, phi1 and phi2 would share more intermediate phi nodes.
858 // This would help reduce the number of phi nodes during SSA reconstruction
859 // and ultimately result in fewer COPY instructions.
860 //
861 // This should be correct, because if a phi node does not have incoming
862 // value from certain block, this means the block is not the predecessor
863 // of the parent block, so we actually don't care about its incoming value.
864 EquivalenceClasses<PHINode *> PhiClasses;
865 for (const auto &[To, From] : AddedPhis) {
866 auto OldPhiIt = DeletedPhis.find(Val: To);
867 if (OldPhiIt == DeletedPhis.end())
868 continue;
869
870 PhiMap &BlkPhis = OldPhiIt->second;
871 SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
872 SmallPtrSet<BasicBlock *, 8> Incomings;
873
874 // Get the undefined blocks shared by all the phi nodes.
875 if (!BlkPhis.empty()) {
876 Incomings.insert_range(R: llvm::make_first_range(c&: BlkPhis.front().second));
877 findUndefBlocks(PHIBlock: To, Incomings, UndefBlks);
878 }
879
880 for (const auto &[Phi, Incomings] : OldPhiIt->second) {
881 SmallVector<PHINode *> IncomingPHIs;
882 for (const auto &[BB, V] : Incomings) {
883 // First, for each phi, check whether it has incoming value which is
884 // another phi.
885 if (PHINode *P = dyn_cast<PHINode>(Val: V))
886 IncomingPHIs.push_back(Elt: P);
887 }
888
889 for (auto *OtherPhi : IncomingPHIs) {
890 // Skip phis that are unrelated to the phi reconstruction for now.
891 if (!DeletedPhis.contains(Val: OtherPhi->getParent()))
892 continue;
893 mergeIfCompatible(PhiClasses, A: Phi, B: OtherPhi);
894 }
895 }
896 }
897
898 for (const auto &AddedPhi : AddedPhis) {
899 BasicBlock *To = AddedPhi.first;
900 const BBVector &From = AddedPhi.second;
901
902 auto It = DeletedPhis.find(Val: To);
903 if (It == DeletedPhis.end())
904 continue;
905
906 PhiMap &Map = It->second;
907 SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
908 for (const auto &[Phi, Incoming] : Map) {
909 Value *Poison = PoisonValue::get(T: Phi->getType());
910 Updater.Initialize(Ty: Phi->getType(), Name: "");
911 Updater.AddAvailableValue(BB: &Func->getEntryBlock(), V: Poison);
912 Updater.AddAvailableValue(BB: To, V: Poison);
913
914 // Use leader phi's incoming if there is.
915 auto LeaderIt = PhiClasses.findLeader(V: Phi);
916 bool UseIncomingOfLeader =
917 LeaderIt != PhiClasses.member_end() && *LeaderIt != Phi;
918 const auto &IncomingMap =
919 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
920 : Incoming;
921
922 SmallVector<BasicBlock *> ConstantPreds;
923 for (const auto &[BB, V] : IncomingMap) {
924 Updater.AddAvailableValue(BB, V);
925 if (isa<Constant>(Val: V))
926 ConstantPreds.push_back(Elt: BB);
927 }
928
929 for (auto UB : UndefBlks) {
930 // If this undef block is dominated by any predecessor(before
931 // structurization) of reconstructed PHI with constant incoming value,
932 // don't mark the available value as undefined. Setting undef to such
933 // block will stop us from getting optimal phi insertion.
934 if (any_of(Range&: ConstantPreds,
935 P: [&](BasicBlock *CP) { return DT->dominates(A: CP, B: UB); }))
936 continue;
937 // Maybe already get a value through sharing with other phi nodes.
938 if (Updater.HasValueForBlock(BB: UB))
939 continue;
940
941 Updater.AddAvailableValue(BB: UB, V: Poison);
942 }
943
944 for (BasicBlock *FI : From)
945 Phi->setIncomingValueForBlock(BB: FI, V: Updater.GetValueAtEndOfBlock(BB: FI));
946 AffectedPhis.push_back(Elt: Phi);
947 }
948 }
949
950 AffectedPhis.append(in_start: InsertedPhis.begin(), in_end: InsertedPhis.end());
951}
952
953/// Updates PHI nodes after hoisted zero cost instructions by replacing poison
954/// entries on Flow nodes with the appropriate hoisted values
955void StructurizeCFG::simplifyHoistedPhis() {
956 for (WeakVH VH : AffectedPhis) {
957 PHINode *Phi = dyn_cast_or_null<PHINode>(Val&: VH);
958 if (!Phi || Phi->getNumIncomingValues() != 2)
959 continue;
960
961 for (int i = 0; i < 2; i++) {
962 Value *V = Phi->getIncomingValue(i);
963 auto BBIt = HoistedValues.find(Val: V);
964
965 if (BBIt == HoistedValues.end())
966 continue;
967
968 Value *OtherV = Phi->getIncomingValue(i: !i);
969 PHINode *OtherPhi = dyn_cast<PHINode>(Val: OtherV);
970 if (!OtherPhi)
971 continue;
972
973 int PoisonValBBIdx = -1;
974 for (size_t i = 0; i < OtherPhi->getNumIncomingValues(); i++) {
975 if (!isa<PoisonValue>(Val: OtherPhi->getIncomingValue(i)))
976 continue;
977 PoisonValBBIdx = i;
978 break;
979 }
980 if (PoisonValBBIdx == -1 ||
981 !DT->dominates(A: BBIt->second,
982 B: OtherPhi->getIncomingBlock(i: PoisonValBBIdx)))
983 continue;
984
985 OtherPhi->setIncomingValue(i: PoisonValBBIdx, V);
986 if (DT->dominates(Def: OtherV, User: Phi))
987 Phi->setIncomingValue(i, V: OtherV);
988 }
989 }
990}
991
992void StructurizeCFG::simplifyAffectedPhis() {
993 bool Changed;
994 do {
995 Changed = false;
996 SimplifyQuery Q(Func->getDataLayout());
997 Q.DT = DT;
998 // Setting CanUseUndef to true might extend value liveness, set it to false
999 // to achieve better register pressure.
1000 Q.CanUseUndef = false;
1001 for (WeakVH VH : AffectedPhis) {
1002 if (auto Phi = dyn_cast_or_null<PHINode>(Val&: VH)) {
1003 if (auto NewValue = simplifyInstruction(I: Phi, Q)) {
1004 Phi->replaceAllUsesWith(V: NewValue);
1005 Phi->eraseFromParent();
1006 Changed = true;
1007 }
1008 }
1009 }
1010 } while (Changed);
1011}
1012
1013/// Remove phi values from all successors and then remove the terminator.
1014DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1015 Instruction *Term = BB->getTerminatorOrNull();
1016 if (!Term)
1017 return DebugLoc();
1018
1019 for (BasicBlock *Succ : successors(BB))
1020 delPhiValues(From: BB, To: Succ);
1021
1022 DebugLoc DL = Term->getDebugLoc();
1023 Term->eraseFromParent();
1024 return DL;
1025}
1026
1027/// Let node exit(s) point to NewExit
1028void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1029 bool IncludeDominator) {
1030 if (Node->isSubRegion()) {
1031 Region *SubRegion = Node->getNodeAs<Region>();
1032 BasicBlock *OldExit = SubRegion->getExit();
1033 BasicBlock *Dominator = nullptr;
1034
1035 // Find all the edges from the sub region to the exit.
1036 // We use make_early_inc_range here because we modify BB's terminator.
1037 for (BasicBlock *BB : llvm::make_early_inc_range(Range: predecessors(BB: OldExit))) {
1038 if (!SubRegion->contains(BB))
1039 continue;
1040
1041 // Modify the edges to point to the new exit
1042 delPhiValues(From: BB, To: OldExit);
1043 BB->getTerminator()->replaceUsesOfWith(From: OldExit, To: NewExit);
1044 addPhiValues(From: BB, To: NewExit);
1045
1046 // Find the new dominator (if requested)
1047 if (IncludeDominator) {
1048 if (!Dominator)
1049 Dominator = BB;
1050 else
1051 Dominator = DT->findNearestCommonDominator(A: Dominator, B: BB);
1052 }
1053 }
1054
1055 // Change the dominator (if requested)
1056 if (Dominator)
1057 DT->changeImmediateDominator(BB: NewExit, NewBB: Dominator);
1058
1059 // Update the region info
1060 SubRegion->replaceExit(BB: NewExit);
1061 } else {
1062 BasicBlock *BB = Node->getNodeAs<BasicBlock>();
1063 DebugLoc DL = killTerminator(BB);
1064 UncondBrInst *Br = UncondBrInst::Create(Target: NewExit, InsertBefore: BB);
1065 Br->setDebugLoc(DL);
1066 addPhiValues(From: BB, To: NewExit);
1067 if (IncludeDominator)
1068 DT->changeImmediateDominator(BB: NewExit, NewBB: BB);
1069 }
1070}
1071
1072/// Create a new flow node and update dominator tree and region info
1073BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1074 LLVMContext &Context = Func->getContext();
1075 BasicBlock *Insert = Order.empty() ? ParentRegion->getExit() :
1076 Order.back()->getEntry();
1077 BasicBlock *Flow = BasicBlock::Create(Context, Name: FlowBlockName,
1078 Parent: Func, InsertBefore: Insert);
1079 FlowSet.insert(Ptr: Flow);
1080 DT->addNewBlock(BB: Flow, DomBB: Dominator);
1081 ParentRegion->getRegionInfo()->setRegionFor(BB: Flow, R: ParentRegion);
1082 return Flow;
1083}
1084
1085/// Create a new or reuse the previous node as flow node. Returns a block and a
1086/// debug location to be used for new instructions in that block.
1087std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(bool NeedEmpty) {
1088 BasicBlock *Entry = PrevNode->getEntry();
1089
1090 if (!PrevNode->isSubRegion()) {
1091 DebugLoc DL = killTerminator(BB: Entry);
1092 if (!NeedEmpty || Entry->getFirstInsertionPt() == Entry->end())
1093 return {Entry, DL};
1094 }
1095
1096 // create a new flow node
1097 BasicBlock *Flow = getNextFlow(Dominator: Entry);
1098
1099 // and wire it up
1100 changeExit(Node: PrevNode, NewExit: Flow, IncludeDominator: true);
1101 PrevNode = ParentRegion->getBBNode(BB: Flow);
1102 return {Flow, DebugLoc()};
1103}
1104
1105/// Returns the region exit if possible, otherwise just a new flow node
1106BasicBlock *StructurizeCFG::needPostfix(BasicBlock *Flow,
1107 bool ExitUseAllowed) {
1108 if (!Order.empty() || !ExitUseAllowed)
1109 return getNextFlow(Dominator: Flow);
1110
1111 BasicBlock *Exit = ParentRegion->getExit();
1112 DT->changeImmediateDominator(BB: Exit, NewBB: Flow);
1113 addPhiValues(From: Flow, To: Exit);
1114 return Exit;
1115}
1116
1117/// Set the previous node
1118void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1119 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB)
1120 : nullptr;
1121}
1122
1123/// Does BB dominate all the predicates of Node?
1124bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1125 BBPredicates &Preds = Predicates[Node->getEntry()];
1126 return llvm::all_of(
1127 Range&: Preds, P: [&](const auto &Pred) { return DT->dominates(BB, Pred.first); });
1128}
1129
1130/// Can we predict that this node will always be called?
1131bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1132 BBPredicates &Preds = Predicates[Node->getEntry()];
1133 bool Dominated = false;
1134
1135 // Regionentry is always true
1136 if (!PrevNode)
1137 return true;
1138
1139 for (auto [BB, PI] : Preds) {
1140 if (PI.Pred != BoolTrue)
1141 return false;
1142
1143 if (!Dominated && DT->dominates(A: BB, B: PrevNode->getEntry()))
1144 Dominated = true;
1145 }
1146
1147 // TODO: The dominator check is too strict
1148 return Dominated;
1149}
1150
1151/// Take one node from the order vector and wire it up
1152void StructurizeCFG::wireFlow(bool ExitUseAllowed,
1153 BasicBlock *LoopEnd) {
1154 RegionNode *Node = Order.pop_back_val();
1155 Visited.insert(Ptr: Node->getEntry());
1156
1157 if (isPredictableTrue(Node)) {
1158 // Just a linear flow
1159 if (PrevNode) {
1160 changeExit(Node: PrevNode, NewExit: Node->getEntry(), IncludeDominator: true);
1161 }
1162 PrevNode = Node;
1163 } else {
1164 // Insert extra prefix node (or reuse last one)
1165 auto [Flow, DL] = needPrefix(NeedEmpty: false);
1166
1167 // Insert extra postfix node (or use exit instead)
1168 BasicBlock *Entry = Node->getEntry();
1169 BasicBlock *Next = needPostfix(Flow, ExitUseAllowed);
1170
1171 // let it point to entry and next block
1172 CondBrInst *Br = CondBrInst::Create(Cond: BoolPoison, IfTrue: Entry, IfFalse: Next, InsertBefore: Flow);
1173 Br->setDebugLoc(DL);
1174 Conditions.push_back(Elt: Br);
1175 addPhiValues(From: Flow, To: Entry);
1176 DT->changeImmediateDominator(BB: Entry, NewBB: Flow);
1177
1178 PrevNode = Node;
1179 while (!Order.empty() && !Visited.count(Ptr: LoopEnd) &&
1180 dominatesPredicates(BB: Entry, Node: Order.back())) {
1181 handleLoops(ExitUseAllowed: false, LoopEnd);
1182 }
1183
1184 changeExit(Node: PrevNode, NewExit: Next, IncludeDominator: false);
1185 setPrevNode(Next);
1186 }
1187}
1188
1189void StructurizeCFG::handleLoops(bool ExitUseAllowed,
1190 BasicBlock *LoopEnd) {
1191 RegionNode *Node = Order.back();
1192 BasicBlock *LoopStart = Node->getEntry();
1193
1194 if (!Loops.count(Val: LoopStart)) {
1195 wireFlow(ExitUseAllowed, LoopEnd);
1196 return;
1197 }
1198
1199 if (!isPredictableTrue(Node))
1200 LoopStart = needPrefix(NeedEmpty: true).first;
1201
1202 LoopEnd = Loops[Node->getEntry()];
1203 wireFlow(ExitUseAllowed: false, LoopEnd);
1204 while (!Visited.count(Ptr: LoopEnd)) {
1205 handleLoops(ExitUseAllowed: false, LoopEnd);
1206 }
1207
1208 assert(LoopStart != &LoopStart->getParent()->getEntryBlock());
1209
1210 // Create an extra loop end node
1211 DebugLoc DL;
1212 std::tie(args&: LoopEnd, args&: DL) = needPrefix(NeedEmpty: false);
1213 BasicBlock *Next = needPostfix(Flow: LoopEnd, ExitUseAllowed);
1214 CondBrInst *Br = CondBrInst::Create(Cond: BoolPoison, IfTrue: Next, IfFalse: LoopStart, InsertBefore: LoopEnd);
1215 Br->setDebugLoc(DL);
1216 LoopConds.push_back(Elt: Br);
1217 addPhiValues(From: LoopEnd, To: LoopStart);
1218 setPrevNode(Next);
1219}
1220
1221/// After this function control flow looks like it should be, but
1222/// branches and PHI nodes only have undefined conditions.
1223void StructurizeCFG::createFlow() {
1224 BasicBlock *Exit = ParentRegion->getExit();
1225 bool EntryDominatesExit = DT->dominates(A: ParentRegion->getEntry(), B: Exit);
1226
1227 AffectedPhis.clear();
1228 DeletedPhis.clear();
1229 AddedPhis.clear();
1230 Conditions.clear();
1231 LoopConds.clear();
1232
1233 PrevNode = nullptr;
1234 Visited.clear();
1235
1236 while (!Order.empty()) {
1237 handleLoops(ExitUseAllowed: EntryDominatesExit, LoopEnd: nullptr);
1238 }
1239
1240 if (PrevNode)
1241 changeExit(Node: PrevNode, NewExit: Exit, IncludeDominator: EntryDominatesExit);
1242 else
1243 assert(EntryDominatesExit);
1244}
1245
1246/// Handle a rare case where the disintegrated nodes instructions
1247/// no longer dominate all their uses.
1248void StructurizeCFG::rebuildSSA() {
1249 SSAUpdater Updater;
1250 for (BasicBlock *BB : ParentRegion->blocks())
1251 for (Instruction &I : *BB) {
1252 bool Initialized = false;
1253 // We may modify the use list as we iterate over it, so we use
1254 // make_early_inc_range.
1255 for (Use &U : llvm::make_early_inc_range(Range: I.uses())) {
1256 Instruction *User = cast<Instruction>(Val: U.getUser());
1257 if (User->getParent() == BB) {
1258 continue;
1259 } else if (PHINode *UserPN = dyn_cast<PHINode>(Val: User)) {
1260 if (UserPN->getIncomingBlock(U) == BB)
1261 continue;
1262 }
1263
1264 if (DT->dominates(Def: &I, User))
1265 continue;
1266
1267 if (!Initialized) {
1268 Value *Poison = PoisonValue::get(T: I.getType());
1269 Updater.Initialize(Ty: I.getType(), Name: "");
1270 Updater.AddAvailableValue(BB: &Func->getEntryBlock(), V: Poison);
1271 Updater.AddAvailableValue(BB, V: &I);
1272 Initialized = true;
1273 }
1274 Updater.RewriteUseAfterInsertions(U);
1275 }
1276 }
1277}
1278
1279/// Can region \p R be left unstructurized because all of its own control flow
1280/// is uniform?
1281///
1282/// Only the terminators of direct child blocks are checked. Sub-regions are
1283/// processed before their parent, so any divergent control flow inside a
1284/// sub-region has already been structurized and is self-contained: it is
1285/// entered only through the sub-region's entry, and it rejoins either at Flow
1286/// blocks inside the sub-region or, if the sub-region's entry dominates its
1287/// exit, at the exit block itself. Uniform control flow around a sub-region
1288/// therefore does not need structurizing, whatever the sub-region contains.
1289/// (The branches inside sub-regions could not be checked anyway, because they
1290/// may have been removed and re-created since UniformityAnalysis ran.)
1291///
1292/// FIXME: This does not hold for a sub-region whose entry block ends in a
1293/// callbr, because run() leaves such regions unstructurized.
1294static bool hasOnlyUniformBranches(Region *R, const UniformityInfo &UA) {
1295 return none_of(Range: R->elements(), P: [&](RegionNode *E) {
1296 if (E->isSubRegion())
1297 return false;
1298 auto *Br = dyn_cast<CondBrInst>(Val: E->getEntry()->getTerminator());
1299 return Br && UA.isDivergentTerminator(I: Br);
1300 });
1301}
1302
1303void StructurizeCFG::init(Region *R) {
1304 LLVMContext &Context = R->getEntry()->getContext();
1305
1306 Boolean = Type::getInt1Ty(C&: Context);
1307 BoolTrue = ConstantInt::getTrue(Context);
1308 BoolFalse = ConstantInt::getFalse(Context);
1309 BoolPoison = PoisonValue::get(T: Boolean);
1310
1311 this->UA = nullptr;
1312}
1313
1314bool StructurizeCFG::makeUniformRegion(Region *R, UniformityInfo &UA) {
1315 if (R->isTopLevelRegion())
1316 return false;
1317
1318 this->UA = &UA;
1319
1320 if (hasOnlyUniformBranches(R, UA)) {
1321 LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R
1322 << '\n');
1323
1324 // Mark all direct child block terminators as having been treated as
1325 // uniform. Indirect children must not be marked, because sub-regions may
1326 // contain divergent control flow.
1327 LLVMContext &Ctx = R->getEntry()->getContext();
1328 unsigned UniformMDKindID = Ctx.getMDKindID(Name: "structurizecfg.uniform");
1329 MDNode *MD = MDNode::get(Context&: Ctx, MDs: {});
1330 for (RegionNode *E : R->elements()) {
1331 if (E->isSubRegion())
1332 continue;
1333
1334 E->getEntry()->getTerminator()->setMetadata(KindID: UniformMDKindID, Node: MD);
1335 }
1336
1337 return true;
1338 }
1339 return false;
1340}
1341
1342/// Run the transformation for each region found
1343bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1344 const TargetTransformInfo *TTI) {
1345 // CallBr and its corresponding direct target blocks are for now ignored by
1346 // this pass. This is not a limitation for the currently intended uses cases
1347 // of callbr in the AMDGPU backend.
1348 // Parent and child regions are not affected by this (current) restriction.
1349 // See `llvm/test/Transforms/StructurizeCFG/callbr.ll` for details.
1350 if (R->isTopLevelRegion() || isa<CallBrInst>(Val: R->getEntry()->getTerminator()))
1351 return false;
1352
1353 this->DT = DT;
1354 this->TTI = TTI;
1355 Func = R->getEntry()->getParent();
1356
1357 ParentRegion = R;
1358
1359 orderNodes();
1360 collectInfos();
1361 createFlow();
1362
1363 SSAUpdaterBulk PhiInserter;
1364 insertConditions(Loops: false, PhiInserter);
1365 insertConditions(Loops: true, PhiInserter);
1366 PhiInserter.RewriteAndOptimizeAllUses(DT&: *DT);
1367
1368 setPhiValues();
1369 simplifyHoistedPhis();
1370 simplifyConditions();
1371 simplifyAffectedPhis();
1372 rebuildSSA();
1373
1374 // Cleanup
1375 Order.clear();
1376 Visited.clear();
1377 DeletedPhis.clear();
1378 AddedPhis.clear();
1379 Predicates.clear();
1380 Conditions.clear();
1381 Loops.clear();
1382 LoopPreds.clear();
1383 LoopConds.clear();
1384 FlowSet.clear();
1385
1386 return true;
1387}
1388
1389Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) {
1390 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1391}
1392
1393static void addRegionIntoQueue(Region &R, std::vector<Region *> &Regions) {
1394 Regions.push_back(x: &R);
1395 for (const auto &E : R)
1396 addRegionIntoQueue(R&: *E, Regions);
1397}
1398
1399StructurizeCFGPass::StructurizeCFGPass(bool SkipUniformRegions_)
1400 : SkipUniformRegions(SkipUniformRegions_) {}
1401
1402void StructurizeCFGPass::printPipeline(
1403 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
1404 static_cast<PassInfoMixin<StructurizeCFGPass> *>(this)->printPipeline(
1405 OS, MapClassName2PassName);
1406 if (SkipUniformRegions)
1407 OS << "<skip-uniform-regions>";
1408}
1409
1410PreservedAnalyses StructurizeCFGPass::run(Function &F,
1411 FunctionAnalysisManager &AM) {
1412
1413 bool Changed = false;
1414 DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(IR&: F);
1415 auto &RI = AM.getResult<RegionInfoAnalysis>(IR&: F);
1416 TargetTransformInfo *TTI = &AM.getResult<TargetIRAnalysis>(IR&: F);
1417 const ScalarOptions &Opts =
1418 F.getContext().getLibraryOptions().get<ScalarOptions>();
1419 bool SkipUniform =
1420 valueOr(X: Opts.structurizecfg_skip_uniform_regions, Default: SkipUniformRegions);
1421 UniformityInfo *UI = nullptr;
1422 if (SkipUniform)
1423 UI = &AM.getResult<UniformityInfoAnalysis>(IR&: F);
1424
1425 std::vector<Region *> Regions;
1426 addRegionIntoQueue(R&: *RI.getTopLevelRegion(), Regions);
1427 while (!Regions.empty()) {
1428 Region *R = Regions.back();
1429 Regions.pop_back();
1430
1431 StructurizeCFG SCFG;
1432 SCFG.init(R);
1433
1434 if (SkipUniform && SCFG.makeUniformRegion(R, UA&: *UI)) {
1435 Changed = true; // May have added metadata.
1436 continue;
1437 }
1438
1439 Changed |= SCFG.run(R, DT, TTI);
1440 }
1441 if (!Changed)
1442 return PreservedAnalyses::all();
1443 PreservedAnalyses PA;
1444 PA.preserve<DominatorTreeAnalysis>();
1445 return PA;
1446}
1447