LLVM 24.0.0git
StructurizeCFG.cpp
Go to the documentation of this file.
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
10#include "ScalarOptions.h"
11#include "llvm/ADT/DenseMap.h"
13#include "llvm/ADT/MapVector.h"
15#include "llvm/ADT/STLExtras.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"
32#include "llvm/IR/Metadata.h"
33#include "llvm/IR/PassManager.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"
41#include "llvm/Pass.h"
43#include "llvm/Support/Debug.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
74
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(Br, T, 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(Br, Arr, 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
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> {
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(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(
160 {GraphTraits<RegionNode *>::child_end(N.first), N.second}),
161 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(Result, 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;
271 Function *Func;
272 Region *ParentRegion;
273
274 UniformityInfo *UA = nullptr;
275 DominatorTree *DT;
276
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 SkipUniformRegions =
372 valueOr(ScalarOptions::Global.structurizecfg_skip_uniform_regions,
373 SkipUniformRegions);
375 }
376
377 bool runOnRegion(Region *R, RGPassManager &RGM) override {
378 StructurizeCFG SCFG;
379 SCFG.init(R);
380 if (SkipUniformRegions) {
381 UniformityInfo &UA =
382 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
383 if (SCFG.makeUniformRegion(R, UA))
384 return false;
385 }
386 Function *F = R->getEntry()->getParent();
387 const TargetTransformInfo *TTI =
388 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*F);
389 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
390 return SCFG.run(R, DT, TTI);
391 }
392
393 StringRef getPassName() const override { return "Structurize control flow"; }
394
395 void getAnalysisUsage(AnalysisUsage &AU) const override {
396 if (SkipUniformRegions)
401
404 }
405};
406
407} // end anonymous namespace
408
409char StructurizeCFGLegacyPass::ID = 0;
410
411INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg",
412 "Structurize the CFG", false, false)
416INITIALIZE_PASS_END(StructurizeCFGLegacyPass, "structurizecfg",
417 "Structurize the CFG", false, false)
418
419/// Checks whether an instruction is zero cost instruction and checks if the
420/// operands are from different BB. If so, this instruction can be coalesced
421/// if its hoisted to predecessor block. So, this returns true.
422bool StructurizeCFG::isHoistableInstruction(Instruction *I, BasicBlock *BB,
423 BasicBlock *HoistTo) {
424 if (I->getParent() != BB || isa<PHINode>(I))
425 return false;
426
427 // If the instruction is not a zero cost instruction, return false.
428 auto Cost = TTI->getInstructionCost(I, TargetTransformInfo::TCK_Latency);
430 Cost.isValid()
431 ? Cost.getValue()
433 if (CostVal != 0)
434 return false;
435
436 // Check if all operands are available at the hoisting destination.
437 for (auto &Op : I->operands()) {
438 if (auto *OpI = dyn_cast<Instruction>(Op)) {
439 // Operand must dominate the hoisting destination.
440 if (!DT->dominates(OpI->getParent(), HoistTo))
441 return false;
442 }
443 }
444
445 return true;
446}
447
448/// Structurization can introduce unnecessary VGPR copies due to register
449/// coalescing interference. For example, if the Else block has a zero-cost
450/// instruction and the Then block modifies the VGPR value, only one value is
451/// live at a time in merge block before structurization. After structurization,
452/// the coalescer may incorrectly treat the Then value as live in the Else block
453/// (via the path Then → Flow → Else), leading to unnecessary VGPR copies.
454///
455/// This function examines phi nodes whose incoming values are zero-cost
456/// instructions in the Else block. It identifies such values that can be safely
457/// hoisted and moves them to the nearest common dominator of Then and Else
458/// blocks. A follow-up function after setting PhiNodes assigns the hoisted
459/// value to poison phi nodes along the if→flow edge, aiding register coalescing
460/// and minimizing unnecessary live ranges.
461void StructurizeCFG::hoistZeroCostElseBlockPhiValues(BasicBlock *ElseBB,
462 BasicBlock *ThenBB) {
463
464 BasicBlock *ElseSucc = ElseBB->getSingleSuccessor();
465 BasicBlock *CommonDominator = DT->findNearestCommonDominator(ElseBB, ThenBB);
466
467 if (!ElseSucc || !CommonDominator)
468 return;
469 // Only hoist in a simple if-else: ThenBB must branch directly to ElseSucc
470 // and ElseSucc must have exactly 2 predecessors (ThenBB and ElseBB).
471 // simplifyHoistedPhis assumes this exact shape; with additional predecessors
472 // the hoisted value leaks into unrelated control-flow paths.
473 if (ThenBB->getSingleSuccessor() != ElseSucc ||
474 !ElseSucc->hasNPredecessors(2))
475 return;
476 Instruction *Term = CommonDominator->getTerminator();
477 for (PHINode &Phi : ElseSucc->phis()) {
478 Value *ElseVal = Phi.getIncomingValueForBlock(ElseBB);
479 auto *Inst = dyn_cast<Instruction>(ElseVal);
480 if (!Inst || !isHoistableInstruction(Inst, ElseBB, CommonDominator))
481 continue;
482 Inst->removeFromParent();
483 Inst->insertInto(CommonDominator, Term->getIterator());
484 HoistedValues[Inst] = CommonDominator;
485 }
486}
487
488/// Build up the general order of nodes, by performing a topological sort of the
489/// parent region's nodes, while ensuring that there is no outer cycle node
490/// between any two inner cycle nodes.
491void StructurizeCFG::orderNodes() {
492 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion),
493 GraphTraits<Region *>::nodes_end(ParentRegion)));
494 if (Order.empty())
495 return;
496
497 SmallDenseSet<RegionNode *> Nodes;
498 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
499
500 // A list of range indices of SCCs in Order, to be processed.
502 unsigned I = 0, E = Order.size();
503 while (true) {
504 // Run through all the SCCs in the subgraph starting with Entry.
505 for (auto SCCI =
507 EntryNode);
508 !SCCI.isAtEnd(); ++SCCI) {
509 auto &SCC = *SCCI;
510
511 // An SCC up to the size of 2, can be reduced to an entry (the last node),
512 // and a possible additional node. Therefore, it is already in order, and
513 // there is no need to add it to the work-list.
514 unsigned Size = SCC.size();
515 if (Size > 2)
516 WorkList.emplace_back(I, I + Size);
517
518 // Add the SCC nodes to the Order array.
519 for (const auto &N : SCC) {
520 assert(I < E && "SCC size mismatch!");
521 Order[I++] = N.first;
522 }
523 }
524 assert(I == E && "SCC size mismatch!");
525
526 // If there are no more SCCs to order, then we are done.
527 if (WorkList.empty())
528 break;
529
530 std::tie(I, E) = WorkList.pop_back_val();
531
532 // Collect the set of nodes in the SCC's subgraph. These are only the
533 // possible child nodes; we do not add the entry (last node) otherwise we
534 // will have the same exact SCC all over again.
535 Nodes.clear();
536 Nodes.insert(Order.begin() + I, Order.begin() + E - 1);
537
538 // Update the entry node.
539 EntryNode.first = Order[E - 1];
540 EntryNode.second = &Nodes;
541 }
542}
543
544/// Determine the end of the loops
545void StructurizeCFG::analyzeLoops(RegionNode *N) {
546 if (N->isSubRegion()) {
547 // Test for exit as back edge
548 BasicBlock *Exit = N->getNodeAs<Region>()->getExit();
549 if (Visited.count(Exit))
550 Loops[Exit] = N->getEntry();
551
552 } else {
553 // Test for successors as back edge
554 // TODO: support other terminators other than branches.
555 BasicBlock *BB = N->getNodeAs<BasicBlock>();
557 for (BasicBlock *Succ : successors(BB))
558 if (Visited.count(Succ))
559 Loops[Succ] = BB;
560 }
561}
562
563/// Build the condition for one edge
564PredInfo StructurizeCFG::buildCondition(CondBrInst *Term, unsigned Idx,
565 bool Invert) {
566 Value *Cond = Term->getCondition();
567 auto Weights = CondBranchWeights::tryParse(*Term);
568 if (Idx != (unsigned)Invert) {
570 if (Weights)
571 Weights = Weights->invert();
572 }
573 return {Cond, Weights};
574}
575
576/// Analyze the predecessors of each block and build up predicates
577void StructurizeCFG::gatherPredicates(RegionNode *N) {
578 RegionInfo *RI = ParentRegion->getRegionInfo();
579 BasicBlock *BB = N->getEntry();
580 BBPredicates &Pred = Predicates[BB];
581 BBPredicates &LPred = LoopPreds[BB];
582
583 for (BasicBlock *P : predecessors(BB)) {
584 // Ignore it if it's a branch from outside into our region entry
585 if (!ParentRegion->contains(P))
586 continue;
587
588 Region *R = RI->getRegionFor(P);
589 if (R == ParentRegion) {
590 if (isa<UncondBrInst>(P->getTerminator())) {
591 if (Visited.count(P))
592 Pred[P] = {BoolTrue, std::nullopt};
593 else
594 LPred[P] = {BoolFalse, std::nullopt};
595 } else if (auto *CondBr = dyn_cast<CondBrInst>(P->getTerminator())) {
596 bool Idx = CondBr->getSuccessor(0) == BB ? 0 : 1;
597 if (Visited.count(P)) {
598 // Normal forward edge
599 // Try to treat Other like an ELSE block
600 BasicBlock *Other = CondBr->getSuccessor(!Idx);
601 if (Visited.count(Other) && !Loops.count(Other) &&
602 !Pred.count(Other) && !Pred.count(P)) {
603 hoistZeroCostElseBlockPhiValues(BB, Other);
604 Pred[Other] = {BoolFalse, std::nullopt};
605 Pred[P] = {BoolTrue, std::nullopt};
606 } else
607 Pred[P] = buildCondition(CondBr, Idx, false);
608 } else {
609 // Back edge
610 LPred[P] = buildCondition(CondBr, Idx, true);
611 }
612 }
613 } else {
614 // It's an exit from a sub region
615 while (R->getParent() != ParentRegion)
616 R = R->getParent();
617
618 // Edge from inside a subregion to its entry, ignore it
619 if (*R == *N)
620 continue;
621
622 BasicBlock *Entry = R->getEntry();
623 if (Visited.count(Entry))
624 Pred[Entry] = {BoolTrue, std::nullopt};
625 else
626 LPred[Entry] = {BoolFalse, std::nullopt};
627 }
628 }
629}
630
631/// Collect various loop and predicate infos
632void StructurizeCFG::collectInfos() {
633 // Reset predicate
634 Predicates.clear();
635
636 // and loop infos
637 Loops.clear();
638 LoopPreds.clear();
639
640 // Reset the visited nodes
641 Visited.clear();
642
643 for (RegionNode *RN : reverse(Order)) {
644 LLVM_DEBUG(dbgs() << "Visiting: "
645 << (RN->isSubRegion() ? "SubRegion with entry: " : "")
646 << RN->getEntry()->getName() << "\n");
647
648 // Analyze all the conditions leading to a node
649 gatherPredicates(RN);
650
651 // Remember that we've seen this node
652 Visited.insert(RN->getEntry());
653
654 // Find the last back edges
655 analyzeLoops(RN);
656 }
657}
658
659/// Insert the missing branch conditions
660void StructurizeCFG::insertConditions(bool Loops, SSAUpdaterBulk &PhiInserter) {
661 BranchVector &Conds = Loops ? LoopConds : Conditions;
662 Value *Default = Loops ? BoolTrue : BoolFalse;
663
664 for (CondBrInst *Term : Conds) {
665 BasicBlock *Parent = Term->getParent();
666 BasicBlock *SuccTrue = Term->getSuccessor(0);
667 BasicBlock *SuccFalse = Term->getSuccessor(1);
668
669 unsigned Variable = PhiInserter.AddVariable("", Boolean);
670 PhiInserter.AddAvailableValue(Variable, Loops ? SuccFalse : Parent,
671 Default);
672
673 BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue];
674
675 NearestCommonDominator Dominator(DT);
676 Dominator.addBlock(Parent);
677
678 PredInfo ParentInfo{nullptr, std::nullopt};
679 for (auto [BB, PI] : Preds) {
680 if (BB == Parent) {
681 ParentInfo = PI;
682 break;
683 }
684 PhiInserter.AddAvailableValue(Variable, BB, PI.Pred);
685 Dominator.addAndRememberBlock(BB);
686 }
687
688 if (ParentInfo.Pred) {
689 Term->setCondition(ParentInfo.Pred);
690 CondBranchWeights::setMetadata(*Term, ParentInfo.Weights);
691 } else {
692 if (!Dominator.resultIsRememberedBlock())
693 PhiInserter.AddAvailableValue(Variable, Dominator.result(), Default);
694
695 PhiInserter.AddUse(Variable, &Term->getOperandUse(0));
696 }
697 }
698}
699
700/// Simplify any inverted conditions that were built by buildConditions.
701void StructurizeCFG::simplifyConditions() {
702 SmallVector<Instruction *> InstToErase;
703 for (auto &I : concat<PredMap::value_type>(Predicates, LoopPreds)) {
704 auto &Preds = I.second;
705 for (auto [BB, PI] : Preds) {
706 Instruction *Inverted;
707 if (match(PI.Pred, m_Not(m_OneUse(m_Instruction(Inverted)))) &&
708 !PI.Pred->use_empty()) {
709 if (auto *InvertedCmp = dyn_cast<CmpInst>(Inverted)) {
710 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
711 PI.Pred->replaceAllUsesWith(InvertedCmp);
712 InstToErase.push_back(cast<Instruction>(PI.Pred));
713 }
714 }
715 }
716 }
717 for (auto *I : InstToErase)
718 I->eraseFromParent();
719}
720
721/// Remove all PHI values coming from "From" into "To" and remember
722/// them in DeletedPhis
723void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
724 PhiMap &Map = DeletedPhis[To];
725 for (PHINode &Phi : To->phis()) {
726 bool Recorded = false;
727 while (Phi.getBasicBlockIndex(From) != -1) {
728 Value *Deleted = Phi.removeIncomingValue(From, false);
729 Map[&Phi].push_back(std::make_pair(From, Deleted));
730 if (!Recorded) {
731 AffectedPhis.push_back(&Phi);
732 Recorded = true;
733 }
734 }
735 }
736}
737
738/// Add a dummy PHI value as soon as we knew the new predecessor
739void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
740 for (PHINode &Phi : To->phis()) {
741 Value *Poison = PoisonValue::get(Phi.getType());
742 Phi.addIncoming(Poison, From);
743 }
744 AddedPhis[To].push_back(From);
745}
746
747/// When we are reconstructing a PHI inside \p PHIBlock with incoming values
748/// from predecessors \p Incomings, we have a chance to mark the available value
749/// from some blocks as undefined. The function will find out all such blocks
750/// and return in \p UndefBlks.
751void StructurizeCFG::findUndefBlocks(
752 BasicBlock *PHIBlock, const SmallPtrSet<BasicBlock *, 8> &Incomings,
753 SmallVector<BasicBlock *> &UndefBlks) const {
754 // We may get a post-structured CFG like below:
755 //
756 // | P1
757 // |/
758 // F1
759 // |\
760 // | N
761 // |/
762 // F2
763 // |\
764 // | P2
765 // |/
766 // F3
767 // |\
768 // B
769 //
770 // B is the block that has a PHI being reconstructed. P1/P2 are predecessors
771 // of B before structurization. F1/F2/F3 are flow blocks inserted during
772 // structurization process. Block N is not a predecessor of B before
773 // structurization, but are placed between the predecessors(P1/P2) of B after
774 // structurization. This usually means that threads went to N never take the
775 // path N->F2->F3->B. For example, the threads take the branch F1->N may
776 // always take the branch F2->P2. So, when we are reconstructing a PHI
777 // originally in B, we can safely say the incoming value from N is undefined.
778 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
779 SmallVector<BasicBlock *, 8> Stack;
780 if (PHIBlock == ParentRegion->getExit()) {
781 for (auto P : predecessors(PHIBlock)) {
782 if (ParentRegion->contains(P))
783 Stack.push_back(P);
784 }
785 } else {
786 append_range(Stack, predecessors(PHIBlock));
787 }
788
789 // Do a backward traversal over the CFG, and stop further searching if
790 // the block is not a Flow. If a block is neither flow block nor the
791 // incoming predecessor, then the incoming value from the block is
792 // undefined value for the PHI being reconstructed.
793 while (!Stack.empty()) {
794 BasicBlock *Current = Stack.pop_back_val();
795 if (!VisitedBlock.insert(Current).second)
796 continue;
797
798 if (FlowSet.contains(Current))
799 llvm::append_range(Stack, predecessors(Current));
800 else if (!Incomings.contains(Current))
801 UndefBlks.push_back(Current);
802 }
803}
804
805// If two phi nodes have compatible incoming values (for each
806// incoming block, either they have the same incoming value or only one phi
807// node has an incoming value), let them share the merged incoming values. The
808// merge process is guided by the equivalence information from \p PhiClasses.
809// The function will possibly update the incoming values of leader phi in
810// DeletedPhis.
811void StructurizeCFG::mergeIfCompatible(
812 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *A, PHINode *B) {
813 auto ItA = PhiClasses.findLeader(PhiClasses.insert(A));
814 auto ItB = PhiClasses.findLeader(PhiClasses.insert(B));
815 // They are already in the same class, no work needed.
816 if (ItA == ItB)
817 return;
818
819 PHINode *LeaderA = *ItA;
820 PHINode *LeaderB = *ItB;
821 BBValueVector &IncomingA = DeletedPhis[LeaderA->getParent()][LeaderA];
822 BBValueVector &IncomingB = DeletedPhis[LeaderB->getParent()][LeaderB];
823
824 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
825 for (auto [BB, V] : IncomingB) {
826 auto BBIt = Mergeable.find(BB);
827 if (BBIt != Mergeable.end() && BBIt->second != V)
828 return;
829 // Either IncomingA does not have this value or IncomingA has the same
830 // value.
831 Mergeable.insert({BB, V});
832 }
833
834 // Update the incoming value of leaderA.
835 IncomingA.assign(Mergeable.begin(), Mergeable.end());
836 PhiClasses.unionSets(ItA, ItB);
837}
838
839/// Add the real PHI value as soon as everything is set up
840void StructurizeCFG::setPhiValues() {
841 SmallVector<PHINode *, 8> InsertedPhis;
842 SSAUpdater Updater(&InsertedPhis);
843 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
844
845 // Find phi nodes that have compatible incoming values (either they have
846 // the same value for the same block or only one phi node has an incoming
847 // value, see example below). We only search again the phi's that are
848 // referenced by another phi, which is the case we care about.
849 //
850 // For example (-- means no incoming value):
851 // phi1 : BB1:phi2 BB2:v BB3:--
852 // phi2: BB1:-- BB2:v BB3:w
853 //
854 // Then we can merge these incoming values and let phi1, phi2 use the
855 // same set of incoming values:
856 //
857 // phi1&phi2: BB1:phi2 BB2:v BB3:w
858 //
859 // By doing this, phi1 and phi2 would share more intermediate phi nodes.
860 // This would help reduce the number of phi nodes during SSA reconstruction
861 // and ultimately result in fewer COPY instructions.
862 //
863 // This should be correct, because if a phi node does not have incoming
864 // value from certain block, this means the block is not the predecessor
865 // of the parent block, so we actually don't care about its incoming value.
866 EquivalenceClasses<PHINode *> PhiClasses;
867 for (const auto &[To, From] : AddedPhis) {
868 auto OldPhiIt = DeletedPhis.find(To);
869 if (OldPhiIt == DeletedPhis.end())
870 continue;
871
872 PhiMap &BlkPhis = OldPhiIt->second;
873 SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
874 SmallPtrSet<BasicBlock *, 8> Incomings;
875
876 // Get the undefined blocks shared by all the phi nodes.
877 if (!BlkPhis.empty()) {
878 Incomings.insert_range(llvm::make_first_range(BlkPhis.front().second));
879 findUndefBlocks(To, Incomings, UndefBlks);
880 }
881
882 for (const auto &[Phi, Incomings] : OldPhiIt->second) {
883 SmallVector<PHINode *> IncomingPHIs;
884 for (const auto &[BB, V] : Incomings) {
885 // First, for each phi, check whether it has incoming value which is
886 // another phi.
887 if (PHINode *P = dyn_cast<PHINode>(V))
888 IncomingPHIs.push_back(P);
889 }
890
891 for (auto *OtherPhi : IncomingPHIs) {
892 // Skip phis that are unrelated to the phi reconstruction for now.
893 if (!DeletedPhis.contains(OtherPhi->getParent()))
894 continue;
895 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
896 }
897 }
898 }
899
900 for (const auto &AddedPhi : AddedPhis) {
901 BasicBlock *To = AddedPhi.first;
902 const BBVector &From = AddedPhi.second;
903
904 auto It = DeletedPhis.find(To);
905 if (It == DeletedPhis.end())
906 continue;
907
908 PhiMap &Map = It->second;
909 SmallVector<BasicBlock *> &UndefBlks = UndefBlksMap[To];
910 for (const auto &[Phi, Incoming] : Map) {
911 Value *Poison = PoisonValue::get(Phi->getType());
912 Updater.Initialize(Phi->getType(), "");
913 Updater.AddAvailableValue(&Func->getEntryBlock(), Poison);
914 Updater.AddAvailableValue(To, Poison);
915
916 // Use leader phi's incoming if there is.
917 auto LeaderIt = PhiClasses.findLeader(Phi);
918 bool UseIncomingOfLeader =
919 LeaderIt != PhiClasses.member_end() && *LeaderIt != Phi;
920 const auto &IncomingMap =
921 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
922 : Incoming;
923
924 SmallVector<BasicBlock *> ConstantPreds;
925 for (const auto &[BB, V] : IncomingMap) {
926 Updater.AddAvailableValue(BB, V);
927 if (isa<Constant>(V))
928 ConstantPreds.push_back(BB);
929 }
930
931 for (auto UB : UndefBlks) {
932 // If this undef block is dominated by any predecessor(before
933 // structurization) of reconstructed PHI with constant incoming value,
934 // don't mark the available value as undefined. Setting undef to such
935 // block will stop us from getting optimal phi insertion.
936 if (any_of(ConstantPreds,
937 [&](BasicBlock *CP) { return DT->dominates(CP, UB); }))
938 continue;
939 // Maybe already get a value through sharing with other phi nodes.
940 if (Updater.HasValueForBlock(UB))
941 continue;
942
943 Updater.AddAvailableValue(UB, Poison);
944 }
945
946 for (BasicBlock *FI : From)
947 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
948 AffectedPhis.push_back(Phi);
949 }
950 }
951
952 AffectedPhis.append(InsertedPhis.begin(), InsertedPhis.end());
953}
954
955/// Updates PHI nodes after hoisted zero cost instructions by replacing poison
956/// entries on Flow nodes with the appropriate hoisted values
957void StructurizeCFG::simplifyHoistedPhis() {
958 for (WeakVH VH : AffectedPhis) {
959 PHINode *Phi = dyn_cast_or_null<PHINode>(VH);
960 if (!Phi || Phi->getNumIncomingValues() != 2)
961 continue;
962
963 for (int i = 0; i < 2; i++) {
964 Value *V = Phi->getIncomingValue(i);
965 auto BBIt = HoistedValues.find(V);
966
967 if (BBIt == HoistedValues.end())
968 continue;
969
970 Value *OtherV = Phi->getIncomingValue(!i);
971 PHINode *OtherPhi = dyn_cast<PHINode>(OtherV);
972 if (!OtherPhi)
973 continue;
974
975 int PoisonValBBIdx = -1;
976 for (size_t i = 0; i < OtherPhi->getNumIncomingValues(); i++) {
977 if (!isa<PoisonValue>(OtherPhi->getIncomingValue(i)))
978 continue;
979 PoisonValBBIdx = i;
980 break;
981 }
982 if (PoisonValBBIdx == -1 ||
983 !DT->dominates(BBIt->second,
984 OtherPhi->getIncomingBlock(PoisonValBBIdx)))
985 continue;
986
987 OtherPhi->setIncomingValue(PoisonValBBIdx, V);
988 if (DT->dominates(OtherV, Phi))
989 Phi->setIncomingValue(i, OtherV);
990 }
991 }
992}
993
994void StructurizeCFG::simplifyAffectedPhis() {
995 bool Changed;
996 do {
997 Changed = false;
998 SimplifyQuery Q(Func->getDataLayout());
999 Q.DT = DT;
1000 // Setting CanUseUndef to true might extend value liveness, set it to false
1001 // to achieve better register pressure.
1002 Q.CanUseUndef = false;
1003 for (WeakVH VH : AffectedPhis) {
1004 if (auto Phi = dyn_cast_or_null<PHINode>(VH)) {
1005 if (auto NewValue = simplifyInstruction(Phi, Q)) {
1006 Phi->replaceAllUsesWith(NewValue);
1007 Phi->eraseFromParent();
1008 Changed = true;
1009 }
1010 }
1011 }
1012 } while (Changed);
1013}
1014
1015/// Remove phi values from all successors and then remove the terminator.
1016DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1018 if (!Term)
1019 return DebugLoc();
1020
1021 for (BasicBlock *Succ : successors(BB))
1022 delPhiValues(BB, Succ);
1023
1024 DebugLoc DL = Term->getDebugLoc();
1025 Term->eraseFromParent();
1026 return DL;
1027}
1028
1029/// Let node exit(s) point to NewExit
1030void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1031 bool IncludeDominator) {
1032 if (Node->isSubRegion()) {
1033 Region *SubRegion = Node->getNodeAs<Region>();
1034 BasicBlock *OldExit = SubRegion->getExit();
1035 BasicBlock *Dominator = nullptr;
1036
1037 // Find all the edges from the sub region to the exit.
1038 // We use make_early_inc_range here because we modify BB's terminator.
1039 for (BasicBlock *BB : llvm::make_early_inc_range(predecessors(OldExit))) {
1040 if (!SubRegion->contains(BB))
1041 continue;
1042
1043 // Modify the edges to point to the new exit
1044 delPhiValues(BB, OldExit);
1045 BB->getTerminator()->replaceUsesOfWith(OldExit, NewExit);
1046 addPhiValues(BB, NewExit);
1047
1048 // Find the new dominator (if requested)
1049 if (IncludeDominator) {
1050 if (!Dominator)
1051 Dominator = BB;
1052 else
1053 Dominator = DT->findNearestCommonDominator(Dominator, BB);
1054 }
1055 }
1056
1057 // Change the dominator (if requested)
1058 if (Dominator)
1059 DT->changeImmediateDominator(NewExit, Dominator);
1060
1061 // Update the region info
1062 SubRegion->replaceExit(NewExit);
1063 } else {
1064 BasicBlock *BB = Node->getNodeAs<BasicBlock>();
1065 DebugLoc DL = killTerminator(BB);
1066 UncondBrInst *Br = UncondBrInst::Create(NewExit, BB);
1067 Br->setDebugLoc(DL);
1068 addPhiValues(BB, NewExit);
1069 if (IncludeDominator)
1070 DT->changeImmediateDominator(NewExit, BB);
1071 }
1072}
1073
1074/// Create a new flow node and update dominator tree and region info
1075BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1076 LLVMContext &Context = Func->getContext();
1077 BasicBlock *Insert = Order.empty() ? ParentRegion->getExit() :
1078 Order.back()->getEntry();
1080 Func, Insert);
1081 FlowSet.insert(Flow);
1082 DT->addNewBlock(Flow, Dominator);
1083 ParentRegion->getRegionInfo()->setRegionFor(Flow, ParentRegion);
1084 return Flow;
1085}
1086
1087/// Create a new or reuse the previous node as flow node. Returns a block and a
1088/// debug location to be used for new instructions in that block.
1089std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(bool NeedEmpty) {
1090 BasicBlock *Entry = PrevNode->getEntry();
1091
1092 if (!PrevNode->isSubRegion()) {
1093 DebugLoc DL = killTerminator(Entry);
1094 if (!NeedEmpty || Entry->getFirstInsertionPt() == Entry->end())
1095 return {Entry, DL};
1096 }
1097
1098 // create a new flow node
1099 BasicBlock *Flow = getNextFlow(Entry);
1100
1101 // and wire it up
1102 changeExit(PrevNode, Flow, true);
1103 PrevNode = ParentRegion->getBBNode(Flow);
1104 return {Flow, DebugLoc()};
1105}
1106
1107/// Returns the region exit if possible, otherwise just a new flow node
1108BasicBlock *StructurizeCFG::needPostfix(BasicBlock *Flow,
1109 bool ExitUseAllowed) {
1110 if (!Order.empty() || !ExitUseAllowed)
1111 return getNextFlow(Flow);
1112
1113 BasicBlock *Exit = ParentRegion->getExit();
1114 DT->changeImmediateDominator(Exit, Flow);
1115 addPhiValues(Flow, Exit);
1116 return Exit;
1117}
1118
1119/// Set the previous node
1120void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1121 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB)
1122 : nullptr;
1123}
1124
1125/// Does BB dominate all the predicates of Node?
1126bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1127 BBPredicates &Preds = Predicates[Node->getEntry()];
1128 return llvm::all_of(
1129 Preds, [&](const auto &Pred) { return DT->dominates(BB, Pred.first); });
1130}
1131
1132/// Can we predict that this node will always be called?
1133bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1134 BBPredicates &Preds = Predicates[Node->getEntry()];
1135 bool Dominated = false;
1136
1137 // Regionentry is always true
1138 if (!PrevNode)
1139 return true;
1140
1141 for (auto [BB, PI] : Preds) {
1142 if (PI.Pred != BoolTrue)
1143 return false;
1144
1145 if (!Dominated && DT->dominates(BB, PrevNode->getEntry()))
1146 Dominated = true;
1147 }
1148
1149 // TODO: The dominator check is too strict
1150 return Dominated;
1151}
1152
1153/// Take one node from the order vector and wire it up
1154void StructurizeCFG::wireFlow(bool ExitUseAllowed,
1155 BasicBlock *LoopEnd) {
1156 RegionNode *Node = Order.pop_back_val();
1157 Visited.insert(Node->getEntry());
1158
1159 if (isPredictableTrue(Node)) {
1160 // Just a linear flow
1161 if (PrevNode) {
1162 changeExit(PrevNode, Node->getEntry(), true);
1163 }
1164 PrevNode = Node;
1165 } else {
1166 // Insert extra prefix node (or reuse last one)
1167 auto [Flow, DL] = needPrefix(false);
1168
1169 // Insert extra postfix node (or use exit instead)
1170 BasicBlock *Entry = Node->getEntry();
1171 BasicBlock *Next = needPostfix(Flow, ExitUseAllowed);
1172
1173 // let it point to entry and next block
1174 CondBrInst *Br = CondBrInst::Create(BoolPoison, Entry, Next, Flow);
1175 Br->setDebugLoc(DL);
1176 Conditions.push_back(Br);
1177 addPhiValues(Flow, Entry);
1178 DT->changeImmediateDominator(Entry, Flow);
1179
1180 PrevNode = Node;
1181 while (!Order.empty() && !Visited.count(LoopEnd) &&
1182 dominatesPredicates(Entry, Order.back())) {
1183 handleLoops(false, LoopEnd);
1184 }
1185
1186 changeExit(PrevNode, Next, false);
1187 setPrevNode(Next);
1188 }
1189}
1190
1191void StructurizeCFG::handleLoops(bool ExitUseAllowed,
1192 BasicBlock *LoopEnd) {
1193 RegionNode *Node = Order.back();
1194 BasicBlock *LoopStart = Node->getEntry();
1195
1196 if (!Loops.count(LoopStart)) {
1197 wireFlow(ExitUseAllowed, LoopEnd);
1198 return;
1199 }
1200
1201 if (!isPredictableTrue(Node))
1202 LoopStart = needPrefix(true).first;
1203
1204 LoopEnd = Loops[Node->getEntry()];
1205 wireFlow(false, LoopEnd);
1206 while (!Visited.count(LoopEnd)) {
1207 handleLoops(false, LoopEnd);
1208 }
1209
1210 assert(LoopStart != &LoopStart->getParent()->getEntryBlock());
1211
1212 // Create an extra loop end node
1213 DebugLoc DL;
1214 std::tie(LoopEnd, DL) = needPrefix(false);
1215 BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed);
1216 CondBrInst *Br = CondBrInst::Create(BoolPoison, Next, LoopStart, LoopEnd);
1217 Br->setDebugLoc(DL);
1218 LoopConds.push_back(Br);
1219 addPhiValues(LoopEnd, LoopStart);
1220 setPrevNode(Next);
1221}
1222
1223/// After this function control flow looks like it should be, but
1224/// branches and PHI nodes only have undefined conditions.
1225void StructurizeCFG::createFlow() {
1226 BasicBlock *Exit = ParentRegion->getExit();
1227 bool EntryDominatesExit = DT->dominates(ParentRegion->getEntry(), Exit);
1228
1229 AffectedPhis.clear();
1230 DeletedPhis.clear();
1231 AddedPhis.clear();
1232 Conditions.clear();
1233 LoopConds.clear();
1234
1235 PrevNode = nullptr;
1236 Visited.clear();
1237
1238 while (!Order.empty()) {
1239 handleLoops(EntryDominatesExit, nullptr);
1240 }
1241
1242 if (PrevNode)
1243 changeExit(PrevNode, Exit, EntryDominatesExit);
1244 else
1245 assert(EntryDominatesExit);
1246}
1247
1248/// Handle a rare case where the disintegrated nodes instructions
1249/// no longer dominate all their uses. Not sure if this is really necessary
1250void StructurizeCFG::rebuildSSA() {
1251 SSAUpdater Updater;
1252 for (BasicBlock *BB : ParentRegion->blocks())
1253 for (Instruction &I : *BB) {
1254 bool Initialized = false;
1255 // We may modify the use list as we iterate over it, so we use
1256 // make_early_inc_range.
1257 for (Use &U : llvm::make_early_inc_range(I.uses())) {
1258 Instruction *User = cast<Instruction>(U.getUser());
1259 if (User->getParent() == BB) {
1260 continue;
1261 } else if (PHINode *UserPN = dyn_cast<PHINode>(User)) {
1262 if (UserPN->getIncomingBlock(U) == BB)
1263 continue;
1264 }
1265
1266 if (DT->dominates(&I, User))
1267 continue;
1268
1269 if (!Initialized) {
1270 Value *Poison = PoisonValue::get(I.getType());
1271 Updater.Initialize(I.getType(), "");
1272 Updater.AddAvailableValue(&Func->getEntryBlock(), Poison);
1273 Updater.AddAvailableValue(BB, &I);
1274 Initialized = true;
1275 }
1276 Updater.RewriteUseAfterInsertions(U);
1277 }
1278 }
1279}
1280
1281static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID,
1282 const UniformityInfo &UA) {
1283 // Bool for if all sub-regions are uniform.
1284 bool SubRegionsAreUniform = true;
1285 // Count of how many direct children are conditional.
1286 unsigned ConditionalDirectChildren = 0;
1287
1288 for (auto *E : R->elements()) {
1289 if (!E->isSubRegion()) {
1290 auto Br = dyn_cast<CondBrInst>(E->getEntry()->getTerminator());
1291 if (!Br)
1292 continue;
1293
1294 if (UA.isDivergentTerminator(Br))
1295 return false;
1296
1297 // One of our direct children is conditional.
1298 ConditionalDirectChildren++;
1299
1300 LLVM_DEBUG(dbgs() << "BB: " << Br->getParent()->getName()
1301 << " has uniform terminator\n");
1302 } else {
1303 // Explicitly refuse to treat regions as uniform if they have non-uniform
1304 // subregions. We cannot rely on UniformityAnalysis for branches in
1305 // subregions because those branches may have been removed and re-created,
1306 // so we look for our metadata instead.
1307 //
1308 // Warning: It would be nice to treat regions as uniform based only on
1309 // their direct child basic blocks' terminators, regardless of whether
1310 // subregions are uniform or not. However, this requires a very careful
1311 // look at SIAnnotateControlFlow to make sure nothing breaks there.
1312 for (auto *BB : E->getNodeAs<Region>()->blocks()) {
1313 auto Br = dyn_cast<CondBrInst>(BB->getTerminator());
1314 if (!Br)
1315 continue;
1316
1317 if (!Br->getMetadata(UniformMDKindID)) {
1318 // Early exit if we cannot have relaxed uniform regions.
1319 if (!ScalarOptions::Global.structurizecfg_relaxed_uniform_regions)
1320 return false;
1321
1322 SubRegionsAreUniform = false;
1323 break;
1324 }
1325 }
1326 }
1327 }
1328
1329 // Our region is uniform if:
1330 // 1. All conditional branches that are direct children are uniform (checked
1331 // above).
1332 // 2. And either:
1333 // a. All sub-regions are uniform.
1334 // b. There is one or less conditional branches among the direct children.
1335 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
1336}
1337
1338void StructurizeCFG::init(Region *R) {
1339 LLVMContext &Context = R->getEntry()->getContext();
1340
1341 Boolean = Type::getInt1Ty(Context);
1342 BoolTrue = ConstantInt::getTrue(Context);
1343 BoolFalse = ConstantInt::getFalse(Context);
1344 BoolPoison = PoisonValue::get(Boolean);
1345
1346 this->UA = nullptr;
1347}
1348
1349bool StructurizeCFG::makeUniformRegion(Region *R, UniformityInfo &UA) {
1350 if (R->isTopLevelRegion())
1351 return false;
1352
1353 this->UA = &UA;
1354
1355 // TODO: We could probably be smarter here with how we handle sub-regions.
1356 // We currently rely on the fact that metadata is set by earlier invocations
1357 // of the pass on sub-regions, and that this metadata doesn't get lost --
1358 // but we shouldn't rely on metadata for correctness!
1359 unsigned UniformMDKindID =
1360 R->getEntry()->getContext().getMDKindID("structurizecfg.uniform");
1361
1362 if (hasOnlyUniformBranches(R, UniformMDKindID, UA)) {
1363 LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R
1364 << '\n');
1365
1366 // Mark all direct child block terminators as having been treated as
1367 // uniform. To account for a possible future in which non-uniform
1368 // sub-regions are treated more cleverly, indirect children are not
1369 // marked as uniform.
1370 MDNode *MD = MDNode::get(R->getEntry()->getParent()->getContext(), {});
1371 for (RegionNode *E : R->elements()) {
1372 if (E->isSubRegion())
1373 continue;
1374
1375 if (Instruction *Term = E->getEntry()->getTerminator())
1376 Term->setMetadata(UniformMDKindID, MD);
1377 }
1378
1379 return true;
1380 }
1381 return false;
1382}
1383
1384/// Run the transformation for each region found
1385bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1386 const TargetTransformInfo *TTI) {
1387 // CallBr and its corresponding direct target blocks are for now ignored by
1388 // this pass. This is not a limitation for the currently intended uses cases
1389 // of callbr in the AMDGPU backend.
1390 // Parent and child regions are not affected by this (current) restriction.
1391 // See `llvm/test/Transforms/StructurizeCFG/callbr.ll` for details.
1392 if (R->isTopLevelRegion() || isa<CallBrInst>(R->getEntry()->getTerminator()))
1393 return false;
1394
1395 this->DT = DT;
1396 this->TTI = TTI;
1397 Func = R->getEntry()->getParent();
1398
1399 ParentRegion = R;
1400
1401 orderNodes();
1402 collectInfos();
1403 createFlow();
1404
1405 SSAUpdaterBulk PhiInserter;
1406 insertConditions(false, PhiInserter);
1407 insertConditions(true, PhiInserter);
1408 PhiInserter.RewriteAndOptimizeAllUses(*DT);
1409
1410 setPhiValues();
1411 simplifyHoistedPhis();
1412 simplifyConditions();
1413 simplifyAffectedPhis();
1414 rebuildSSA();
1415
1416 // Cleanup
1417 Order.clear();
1418 Visited.clear();
1419 DeletedPhis.clear();
1420 AddedPhis.clear();
1421 Predicates.clear();
1422 Conditions.clear();
1423 Loops.clear();
1424 LoopPreds.clear();
1425 LoopConds.clear();
1426 FlowSet.clear();
1427
1428 return true;
1429}
1430
1431Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) {
1432 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1433}
1434
1435static void addRegionIntoQueue(Region &R, std::vector<Region *> &Regions) {
1436 Regions.push_back(&R);
1437 for (const auto &E : R)
1438 addRegionIntoQueue(*E, Regions);
1439}
1440
1442 : SkipUniformRegions(SkipUniformRegions_) {
1443 SkipUniformRegions =
1444 valueOr(ScalarOptions::Global.structurizecfg_skip_uniform_regions,
1445 SkipUniformRegions);
1446}
1447
1449 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
1450 static_cast<PassInfoMixin<StructurizeCFGPass> *>(this)->printPipeline(
1451 OS, MapClassName2PassName);
1452 if (SkipUniformRegions)
1453 OS << "<skip-uniform-regions>";
1454}
1455
1458
1459 bool Changed = false;
1461 auto &RI = AM.getResult<RegionInfoAnalysis>(F);
1463 UniformityInfo *UI = nullptr;
1464 if (SkipUniformRegions)
1466
1467 std::vector<Region *> Regions;
1468 addRegionIntoQueue(*RI.getTopLevelRegion(), Regions);
1469 while (!Regions.empty()) {
1470 Region *R = Regions.back();
1471 Regions.pop_back();
1472
1473 StructurizeCFG SCFG;
1474 SCFG.init(R);
1475
1476 if (SkipUniformRegions && SCFG.makeUniformRegion(R, *UI)) {
1477 Changed = true; // May have added metadata.
1478 continue;
1479 }
1480
1481 Changed |= SCFG.run(R, DT, TTI);
1482 }
1483 if (!Changed)
1484 return PreservedAnalyses::all();
1487 return PA;
1488}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DenseMap< BasicBlock *, Instruction * > BBPredicates
This file defines the DenseMap class.
@ Default
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Hexagon Hardware Loops
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file implements a map that provides insertion order iteration.
This file contains the declarations for metadata subclasses.
#define T
#define P(N)
if(PassOpts->AAPipeline)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
static void addRegionIntoQueue(Region &R, std::deque< Region * > &RQ)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
Annotate SI Control Flow
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
SmallDenseMap< const PHINode *, PhiInfo, 16 > PhiMap
const char FlowBlockName[]
static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, const UniformityInfo &UA)
#define LLVM_DEBUG(...)
Definition Debug.h:119
This pass exposes codegen information to IR-level passes.
LLVM IR instance of the generic uniformity analysis.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:515
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
LLVM_ABI bool hasNPredecessors(unsigned N) const
Return true if this block has exactly N predecessors.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition BasicBlock.h:248
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Conditional Branch instruction.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
A debug info location.
Definition DebugLoc.h:126
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:763
bool empty() const
Definition DenseMap.h:717
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:277
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
const ECValue & insert(const ElemTy &Data)
Insert a new value into the union/find set, ignoring the request if the value already exists.
member_iterator member_end() const
member_iterator findLeader(const ElemTy &V) const
Given a value in the set, return a member iterator for the equivalence class it is in.
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
const BasicBlock & getEntryBlock() const
Definition Function.h:794
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:360
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
bool isDivergentTerminator(const InstructionT *I) const
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
void setIncomingValue(unsigned i, Value *V)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
Definition Pass.h:99
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition Pass.cpp:113
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
The pass manager to schedule RegionPasses.
Definition RegionPass.h:88
void replaceExit(BlockT *BB)
Replace the exit basic block of the region with the new basic block.
block_range blocks()
Returns a range view of the basic blocks in the region.
Definition RegionInfo.h:620
BlockT * getExit() const
Get the exit BasicBlock of the Region.
Definition RegionInfo.h:357
RegionNodeT * getBBNode(BlockT *BB) const
Get the BasicBlock RegionNode for a BasicBlock.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
RegionInfoT * getRegionInfo() const
Return the RegionInfo object, that belongs to this Region.
Definition RegionInfo.h:424
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
Definition RegionInfo.h:320
Analysis pass that exposes the RegionInfo for a function.
Definition RegionInfo.h:971
RegionT * getRegionFor(BlockT *BB) const
Get the smallest region that contains a BasicBlock.
bool isSubRegion() const
Is this RegionNode a subregion?
Definition RegionInfo.h:186
BlockT * getEntry() const
Get the entry BasicBlock of this RegionNode.
Definition RegionInfo.h:172
A pass that runs on each Region in a function.
Definition RegionPass.h:33
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI unsigned AddVariable(StringRef Name, Type *Ty)
Add a new variable to the SSA rewriter.
LLVM_ABI void AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
LLVM_ABI void AddUse(unsigned Var, Use *U)
Record a use of the symbolic value.
LLVM_ABI void RewriteAndOptimizeAllUses(DominatorTree &DT)
Rewrite all uses and simplify the inserted PHI nodes.
LLVM_ABI void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:293
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Analysis pass providing the TargetTransformInfo.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
@ TCK_Latency
The latency of instruction.
@ TCC_Expensive
The cost of a 'div' instruction on x86.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
Analysis pass which computes UniformityInfo.
Legacy analysis pass which computes a CycleInfo.
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:25
LLVM Value Representation.
Definition Value.h:75
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
CRTP base class for adapting an iterator to a different type.
Definition iterator.h:240
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
static scc_iterator begin(const GraphT &G)
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
Changed
@ Entry
Definition COFF.h:862
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
unsigned char Boolean
Definition ConvertUTF.h:132
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
APInt operator*(APInt a, uint64_t RHS)
Definition APInt.h:2261
auto successors(const MachineBasicBlock *BB)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
LLVM_ABI Pass * createStructurizeCFGPass(bool SkipUniformRegions=false)
When SkipUniformRegions is true the structizer will not structurize regions that only contain uniform...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1167
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
LLVM_ABI void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected, bool ElideAllZero=false)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
Definition STLExtras.h:1415
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:552
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Other
Any other memory.
Definition ModRef.h:68
TargetTransformInfo TTI
DWARFExpression::Operation Op
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto predecessors(const MachineBasicBlock *BB)
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
constexpr bool valueOr(BoolOrDefault X, bool Default)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI Value * invertCondition(Value *Condition)
Invert the given true/false value, possibly reusing an existing copy.
Definition Local.cpp:4000
filter_iterator_impl< WrappedIteratorT, PredicateT, detail::fwd_or_bidi_tag< WrappedIteratorT > > filter_iterator
Defines filter_iterator to a suitable specialization of filter_iterator_impl, based on the underlying...
Definition STLExtras.h:539
LLVM_ABI void initializeStructurizeCFGLegacyPassPass(PassRegistry &)
#define N
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI StructurizeCFGPass(bool SkipUniformRegions=false)