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 "llvm/ADT/DenseMap.h" 11 #include "llvm/ADT/MapVector.h" 12 #include "llvm/ADT/SCCIterator.h" 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/SmallPtrSet.h" 15 #include "llvm/ADT/SmallSet.h" 16 #include "llvm/ADT/SmallVector.h" 17 #include "llvm/Analysis/InstructionSimplify.h" 18 #include "llvm/Analysis/RegionInfo.h" 19 #include "llvm/Analysis/RegionIterator.h" 20 #include "llvm/Analysis/RegionPass.h" 21 #include "llvm/Analysis/UniformityAnalysis.h" 22 #include "llvm/IR/BasicBlock.h" 23 #include "llvm/IR/CFG.h" 24 #include "llvm/IR/Constants.h" 25 #include "llvm/IR/Dominators.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/IR/InstrTypes.h" 28 #include "llvm/IR/Instruction.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/Metadata.h" 31 #include "llvm/IR/PassManager.h" 32 #include "llvm/IR/PatternMatch.h" 33 #include "llvm/IR/ProfDataUtils.h" 34 #include "llvm/IR/Type.h" 35 #include "llvm/IR/Use.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/IR/ValueHandle.h" 38 #include "llvm/InitializePasses.h" 39 #include "llvm/Pass.h" 40 #include "llvm/Support/Casting.h" 41 #include "llvm/Support/CommandLine.h" 42 #include "llvm/Support/Debug.h" 43 #include "llvm/Support/raw_ostream.h" 44 #include "llvm/Transforms/Scalar.h" 45 #include "llvm/Transforms/Utils.h" 46 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 47 #include "llvm/Transforms/Utils/Local.h" 48 #include "llvm/Transforms/Utils/SSAUpdater.h" 49 #include <algorithm> 50 #include <cassert> 51 #include <utility> 52 53 using namespace llvm; 54 using namespace llvm::PatternMatch; 55 56 #define DEBUG_TYPE "structurizecfg" 57 58 // The name for newly created blocks. 59 const char FlowBlockName[] = "Flow"; 60 61 namespace { 62 63 static cl::opt<bool> ForceSkipUniformRegions( 64 "structurizecfg-skip-uniform-regions", 65 cl::Hidden, 66 cl::desc("Force whether the StructurizeCFG pass skips uniform regions"), 67 cl::init(false)); 68 69 static cl::opt<bool> 70 RelaxedUniformRegions("structurizecfg-relaxed-uniform-regions", cl::Hidden, 71 cl::desc("Allow relaxed uniform region checks"), 72 cl::init(true)); 73 74 // Definition of the complex types used in this pass. 75 76 using BBValuePair = std::pair<BasicBlock *, Value *>; 77 78 using RNVector = SmallVector<RegionNode *, 8>; 79 using BBVector = SmallVector<BasicBlock *, 8>; 80 using BranchVector = SmallVector<BranchInst *, 8>; 81 using BBValueVector = SmallVector<BBValuePair, 2>; 82 83 using BBSet = SmallPtrSet<BasicBlock *, 8>; 84 85 using PhiMap = MapVector<PHINode *, BBValueVector>; 86 using BB2BBVecMap = MapVector<BasicBlock *, BBVector>; 87 88 using BBPhiMap = DenseMap<BasicBlock *, PhiMap>; 89 90 using MaybeCondBranchWeights = std::optional<class CondBranchWeights>; 91 92 class CondBranchWeights { 93 uint32_t TrueWeight; 94 uint32_t FalseWeight; 95 96 CondBranchWeights(uint32_t T, uint32_t F) : TrueWeight(T), FalseWeight(F) {} 97 98 public: 99 static MaybeCondBranchWeights tryParse(const BranchInst &Br) { 100 assert(Br.isConditional()); 101 102 uint64_t T, F; 103 if (!extractBranchWeights(Br, T, F)) 104 return std::nullopt; 105 106 return CondBranchWeights(T, F); 107 } 108 109 static void setMetadata(BranchInst &Br, 110 const MaybeCondBranchWeights &Weights) { 111 assert(Br.isConditional()); 112 if (!Weights) 113 return; 114 uint32_t Arr[] = {Weights->TrueWeight, Weights->FalseWeight}; 115 setBranchWeights(Br, Arr, false); 116 } 117 118 CondBranchWeights invert() const { 119 return CondBranchWeights{FalseWeight, TrueWeight}; 120 } 121 }; 122 123 using ValueWeightPair = std::pair<Value *, MaybeCondBranchWeights>; 124 125 using BBPredicates = DenseMap<BasicBlock *, ValueWeightPair>; 126 using PredMap = DenseMap<BasicBlock *, BBPredicates>; 127 using BB2BBMap = DenseMap<BasicBlock *, BasicBlock *>; 128 129 using BranchDebugLocMap = DenseMap<BasicBlock *, DebugLoc>; 130 131 // A traits type that is intended to be used in graph algorithms. The graph 132 // traits starts at an entry node, and traverses the RegionNodes that are in 133 // the Nodes set. 134 struct SubGraphTraits { 135 using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>; 136 using BaseSuccIterator = GraphTraits<RegionNode *>::ChildIteratorType; 137 138 // This wraps a set of Nodes into the iterator, so we know which edges to 139 // filter out. 140 class WrappedSuccIterator 141 : public iterator_adaptor_base< 142 WrappedSuccIterator, BaseSuccIterator, 143 typename std::iterator_traits<BaseSuccIterator>::iterator_category, 144 NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> { 145 SmallDenseSet<RegionNode *> *Nodes; 146 147 public: 148 WrappedSuccIterator(BaseSuccIterator It, SmallDenseSet<RegionNode *> *Nodes) 149 : iterator_adaptor_base(It), Nodes(Nodes) {} 150 151 NodeRef operator*() const { return {*I, Nodes}; } 152 }; 153 154 static bool filterAll(const NodeRef &N) { return true; } 155 static bool filterSet(const NodeRef &N) { return N.second->count(N.first); } 156 157 using ChildIteratorType = 158 filter_iterator<WrappedSuccIterator, bool (*)(const NodeRef &)>; 159 160 static NodeRef getEntryNode(Region *R) { 161 return {GraphTraits<Region *>::getEntryNode(R), nullptr}; 162 } 163 164 static NodeRef getEntryNode(NodeRef N) { return N; } 165 166 static iterator_range<ChildIteratorType> children(const NodeRef &N) { 167 auto *filter = N.second ? &filterSet : &filterAll; 168 return make_filter_range( 169 make_range<WrappedSuccIterator>( 170 {GraphTraits<RegionNode *>::child_begin(N.first), N.second}, 171 {GraphTraits<RegionNode *>::child_end(N.first), N.second}), 172 filter); 173 } 174 175 static ChildIteratorType child_begin(const NodeRef &N) { 176 return children(N).begin(); 177 } 178 179 static ChildIteratorType child_end(const NodeRef &N) { 180 return children(N).end(); 181 } 182 }; 183 184 /// Finds the nearest common dominator of a set of BasicBlocks. 185 /// 186 /// For every BB you add to the set, you can specify whether we "remember" the 187 /// block. When you get the common dominator, you can also ask whether it's one 188 /// of the blocks we remembered. 189 class NearestCommonDominator { 190 DominatorTree *DT; 191 BasicBlock *Result = nullptr; 192 bool ResultIsRemembered = false; 193 194 /// Add BB to the resulting dominator. 195 void addBlock(BasicBlock *BB, bool Remember) { 196 if (!Result) { 197 Result = BB; 198 ResultIsRemembered = Remember; 199 return; 200 } 201 202 BasicBlock *NewResult = DT->findNearestCommonDominator(Result, BB); 203 if (NewResult != Result) 204 ResultIsRemembered = false; 205 if (NewResult == BB) 206 ResultIsRemembered |= Remember; 207 Result = NewResult; 208 } 209 210 public: 211 explicit NearestCommonDominator(DominatorTree *DomTree) : DT(DomTree) {} 212 213 void addBlock(BasicBlock *BB) { 214 addBlock(BB, /* Remember = */ false); 215 } 216 217 void addAndRememberBlock(BasicBlock *BB) { 218 addBlock(BB, /* Remember = */ true); 219 } 220 221 /// Get the nearest common dominator of all the BBs added via addBlock() and 222 /// addAndRememberBlock(). 223 BasicBlock *result() { return Result; } 224 225 /// Is the BB returned by getResult() one of the blocks we added to the set 226 /// with addAndRememberBlock()? 227 bool resultIsRememberedBlock() { return ResultIsRemembered; } 228 }; 229 230 /// Transforms the control flow graph on one single entry/exit region 231 /// at a time. 232 /// 233 /// After the transform all "If"/"Then"/"Else" style control flow looks like 234 /// this: 235 /// 236 /// \verbatim 237 /// 1 238 /// || 239 /// | | 240 /// 2 | 241 /// | / 242 /// |/ 243 /// 3 244 /// || Where: 245 /// | | 1 = "If" block, calculates the condition 246 /// 4 | 2 = "Then" subregion, runs if the condition is true 247 /// | / 3 = "Flow" blocks, newly inserted flow blocks, rejoins the flow 248 /// |/ 4 = "Else" optional subregion, runs if the condition is false 249 /// 5 5 = "End" block, also rejoins the control flow 250 /// \endverbatim 251 /// 252 /// Control flow is expressed as a branch where the true exit goes into the 253 /// "Then"/"Else" region, while the false exit skips the region 254 /// The condition for the optional "Else" region is expressed as a PHI node. 255 /// The incoming values of the PHI node are true for the "If" edge and false 256 /// for the "Then" edge. 257 /// 258 /// Additionally to that even complicated loops look like this: 259 /// 260 /// \verbatim 261 /// 1 262 /// || 263 /// | | 264 /// 2 ^ Where: 265 /// | / 1 = "Entry" block 266 /// |/ 2 = "Loop" optional subregion, with all exits at "Flow" block 267 /// 3 3 = "Flow" block, with back edge to entry block 268 /// | 269 /// \endverbatim 270 /// 271 /// The back edge of the "Flow" block is always on the false side of the branch 272 /// while the true side continues the general flow. So the loop condition 273 /// consist of a network of PHI nodes where the true incoming values expresses 274 /// breaks and the false values expresses continue states. 275 276 class StructurizeCFG { 277 Type *Boolean; 278 ConstantInt *BoolTrue; 279 ConstantInt *BoolFalse; 280 Value *BoolPoison; 281 282 Function *Func; 283 Region *ParentRegion; 284 285 UniformityInfo *UA = nullptr; 286 DominatorTree *DT; 287 288 SmallVector<RegionNode *, 8> Order; 289 BBSet Visited; 290 BBSet FlowSet; 291 292 SmallVector<WeakVH, 8> AffectedPhis; 293 BBPhiMap DeletedPhis; 294 BB2BBVecMap AddedPhis; 295 296 PredMap Predicates; 297 BranchVector Conditions; 298 299 BB2BBMap Loops; 300 PredMap LoopPreds; 301 BranchVector LoopConds; 302 303 BranchDebugLocMap TermDL; 304 305 RegionNode *PrevNode; 306 307 void orderNodes(); 308 309 void analyzeLoops(RegionNode *N); 310 311 ValueWeightPair buildCondition(BranchInst *Term, unsigned Idx, bool Invert); 312 313 void gatherPredicates(RegionNode *N); 314 315 void collectInfos(); 316 317 void insertConditions(bool Loops); 318 319 void simplifyConditions(); 320 321 void delPhiValues(BasicBlock *From, BasicBlock *To); 322 323 void addPhiValues(BasicBlock *From, BasicBlock *To); 324 325 void findUndefBlocks(BasicBlock *PHIBlock, 326 const SmallSet<BasicBlock *, 8> &Incomings, 327 SmallVector<BasicBlock *> &UndefBlks) const; 328 void setPhiValues(); 329 330 void simplifyAffectedPhis(); 331 332 void killTerminator(BasicBlock *BB); 333 334 void changeExit(RegionNode *Node, BasicBlock *NewExit, 335 bool IncludeDominator); 336 337 BasicBlock *getNextFlow(BasicBlock *Dominator); 338 339 BasicBlock *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 357 public: 358 void init(Region *R); 359 bool run(Region *R, DominatorTree *DT); 360 bool makeUniformRegion(Region *R, UniformityInfo &UA); 361 }; 362 363 class StructurizeCFGLegacyPass : public RegionPass { 364 bool SkipUniformRegions; 365 366 public: 367 static char ID; 368 369 explicit StructurizeCFGLegacyPass(bool SkipUniformRegions_ = false) 370 : RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) { 371 if (ForceSkipUniformRegions.getNumOccurrences()) 372 SkipUniformRegions = ForceSkipUniformRegions.getValue(); 373 initializeStructurizeCFGLegacyPassPass(*PassRegistry::getPassRegistry()); 374 } 375 376 bool runOnRegion(Region *R, RGPassManager &RGM) override { 377 StructurizeCFG SCFG; 378 SCFG.init(R); 379 if (SkipUniformRegions) { 380 UniformityInfo &UA = 381 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo(); 382 if (SCFG.makeUniformRegion(R, UA)) 383 return false; 384 } 385 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 386 return SCFG.run(R, DT); 387 } 388 389 StringRef getPassName() const override { return "Structurize control flow"; } 390 391 void getAnalysisUsage(AnalysisUsage &AU) const override { 392 if (SkipUniformRegions) 393 AU.addRequired<UniformityInfoWrapperPass>(); 394 AU.addRequired<DominatorTreeWrapperPass>(); 395 396 AU.addPreserved<DominatorTreeWrapperPass>(); 397 RegionPass::getAnalysisUsage(AU); 398 } 399 }; 400 401 } // end anonymous namespace 402 403 char StructurizeCFGLegacyPass::ID = 0; 404 405 INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg", 406 "Structurize the CFG", false, false) 407 INITIALIZE_PASS_DEPENDENCY(UniformityInfoWrapperPass) 408 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 409 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass) 410 INITIALIZE_PASS_END(StructurizeCFGLegacyPass, "structurizecfg", 411 "Structurize the CFG", false, false) 412 413 /// Build up the general order of nodes, by performing a topological sort of the 414 /// parent region's nodes, while ensuring that there is no outer cycle node 415 /// between any two inner cycle nodes. 416 void StructurizeCFG::orderNodes() { 417 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion), 418 GraphTraits<Region *>::nodes_end(ParentRegion))); 419 if (Order.empty()) 420 return; 421 422 SmallDenseSet<RegionNode *> Nodes; 423 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion); 424 425 // A list of range indices of SCCs in Order, to be processed. 426 SmallVector<std::pair<unsigned, unsigned>, 8> WorkList; 427 unsigned I = 0, E = Order.size(); 428 while (true) { 429 // Run through all the SCCs in the subgraph starting with Entry. 430 for (auto SCCI = 431 scc_iterator<SubGraphTraits::NodeRef, SubGraphTraits>::begin( 432 EntryNode); 433 !SCCI.isAtEnd(); ++SCCI) { 434 auto &SCC = *SCCI; 435 436 // An SCC up to the size of 2, can be reduced to an entry (the last node), 437 // and a possible additional node. Therefore, it is already in order, and 438 // there is no need to add it to the work-list. 439 unsigned Size = SCC.size(); 440 if (Size > 2) 441 WorkList.emplace_back(I, I + Size); 442 443 // Add the SCC nodes to the Order array. 444 for (const auto &N : SCC) { 445 assert(I < E && "SCC size mismatch!"); 446 Order[I++] = N.first; 447 } 448 } 449 assert(I == E && "SCC size mismatch!"); 450 451 // If there are no more SCCs to order, then we are done. 452 if (WorkList.empty()) 453 break; 454 455 std::tie(I, E) = WorkList.pop_back_val(); 456 457 // Collect the set of nodes in the SCC's subgraph. These are only the 458 // possible child nodes; we do not add the entry (last node) otherwise we 459 // will have the same exact SCC all over again. 460 Nodes.clear(); 461 Nodes.insert(Order.begin() + I, Order.begin() + E - 1); 462 463 // Update the entry node. 464 EntryNode.first = Order[E - 1]; 465 EntryNode.second = &Nodes; 466 } 467 } 468 469 /// Determine the end of the loops 470 void StructurizeCFG::analyzeLoops(RegionNode *N) { 471 if (N->isSubRegion()) { 472 // Test for exit as back edge 473 BasicBlock *Exit = N->getNodeAs<Region>()->getExit(); 474 if (Visited.count(Exit)) 475 Loops[Exit] = N->getEntry(); 476 477 } else { 478 // Test for successors as back edge 479 BasicBlock *BB = N->getNodeAs<BasicBlock>(); 480 BranchInst *Term = cast<BranchInst>(BB->getTerminator()); 481 482 for (BasicBlock *Succ : Term->successors()) 483 if (Visited.count(Succ)) 484 Loops[Succ] = BB; 485 } 486 } 487 488 /// Build the condition for one edge 489 ValueWeightPair StructurizeCFG::buildCondition(BranchInst *Term, unsigned Idx, 490 bool Invert) { 491 Value *Cond = Invert ? BoolFalse : BoolTrue; 492 MaybeCondBranchWeights Weights; 493 494 if (Term->isConditional()) { 495 Cond = Term->getCondition(); 496 Weights = CondBranchWeights::tryParse(*Term); 497 498 if (Idx != (unsigned)Invert) { 499 Cond = invertCondition(Cond); 500 if (Weights) 501 Weights = Weights->invert(); 502 } 503 } 504 return {Cond, Weights}; 505 } 506 507 /// Analyze the predecessors of each block and build up predicates 508 void StructurizeCFG::gatherPredicates(RegionNode *N) { 509 RegionInfo *RI = ParentRegion->getRegionInfo(); 510 BasicBlock *BB = N->getEntry(); 511 BBPredicates &Pred = Predicates[BB]; 512 BBPredicates &LPred = LoopPreds[BB]; 513 514 for (BasicBlock *P : predecessors(BB)) { 515 // Ignore it if it's a branch from outside into our region entry 516 if (!ParentRegion->contains(P)) 517 continue; 518 519 Region *R = RI->getRegionFor(P); 520 if (R == ParentRegion) { 521 // It's a top level block in our region 522 BranchInst *Term = cast<BranchInst>(P->getTerminator()); 523 for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) { 524 BasicBlock *Succ = Term->getSuccessor(i); 525 if (Succ != BB) 526 continue; 527 528 if (Visited.count(P)) { 529 // Normal forward edge 530 if (Term->isConditional()) { 531 // Try to treat it like an ELSE block 532 BasicBlock *Other = Term->getSuccessor(!i); 533 if (Visited.count(Other) && !Loops.count(Other) && 534 !Pred.count(Other) && !Pred.count(P)) { 535 536 Pred[Other] = {BoolFalse, std::nullopt}; 537 Pred[P] = {BoolTrue, std::nullopt}; 538 continue; 539 } 540 } 541 Pred[P] = buildCondition(Term, i, false); 542 } else { 543 // Back edge 544 LPred[P] = buildCondition(Term, i, true); 545 } 546 } 547 } else { 548 // It's an exit from a sub region 549 while (R->getParent() != ParentRegion) 550 R = R->getParent(); 551 552 // Edge from inside a subregion to its entry, ignore it 553 if (*R == *N) 554 continue; 555 556 BasicBlock *Entry = R->getEntry(); 557 if (Visited.count(Entry)) 558 Pred[Entry] = {BoolTrue, std::nullopt}; 559 else 560 LPred[Entry] = {BoolFalse, std::nullopt}; 561 } 562 } 563 } 564 565 /// Collect various loop and predicate infos 566 void StructurizeCFG::collectInfos() { 567 // Reset predicate 568 Predicates.clear(); 569 570 // and loop infos 571 Loops.clear(); 572 LoopPreds.clear(); 573 574 // Reset the visited nodes 575 Visited.clear(); 576 577 for (RegionNode *RN : reverse(Order)) { 578 LLVM_DEBUG(dbgs() << "Visiting: " 579 << (RN->isSubRegion() ? "SubRegion with entry: " : "") 580 << RN->getEntry()->getName() << "\n"); 581 582 // Analyze all the conditions leading to a node 583 gatherPredicates(RN); 584 585 // Remember that we've seen this node 586 Visited.insert(RN->getEntry()); 587 588 // Find the last back edges 589 analyzeLoops(RN); 590 } 591 592 // Reset the collected term debug locations 593 TermDL.clear(); 594 595 for (BasicBlock &BB : *Func) { 596 if (const DebugLoc &DL = BB.getTerminator()->getDebugLoc()) 597 TermDL[&BB] = DL; 598 } 599 } 600 601 /// Insert the missing branch conditions 602 void StructurizeCFG::insertConditions(bool Loops) { 603 BranchVector &Conds = Loops ? LoopConds : Conditions; 604 Value *Default = Loops ? BoolTrue : BoolFalse; 605 SSAUpdater PhiInserter; 606 607 for (BranchInst *Term : Conds) { 608 assert(Term->isConditional()); 609 610 BasicBlock *Parent = Term->getParent(); 611 BasicBlock *SuccTrue = Term->getSuccessor(0); 612 BasicBlock *SuccFalse = Term->getSuccessor(1); 613 614 PhiInserter.Initialize(Boolean, ""); 615 PhiInserter.AddAvailableValue(&Func->getEntryBlock(), Default); 616 PhiInserter.AddAvailableValue(Loops ? SuccFalse : Parent, Default); 617 618 BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue]; 619 620 NearestCommonDominator Dominator(DT); 621 Dominator.addBlock(Parent); 622 623 Value *ParentValue = nullptr; 624 MaybeCondBranchWeights ParentWeights = std::nullopt; 625 for (std::pair<BasicBlock *, ValueWeightPair> BBAndPred : Preds) { 626 BasicBlock *BB = BBAndPred.first; 627 auto [Pred, Weight] = BBAndPred.second; 628 629 if (BB == Parent) { 630 ParentValue = Pred; 631 ParentWeights = Weight; 632 break; 633 } 634 PhiInserter.AddAvailableValue(BB, Pred); 635 Dominator.addAndRememberBlock(BB); 636 } 637 638 if (ParentValue) { 639 Term->setCondition(ParentValue); 640 CondBranchWeights::setMetadata(*Term, ParentWeights); 641 } else { 642 if (!Dominator.resultIsRememberedBlock()) 643 PhiInserter.AddAvailableValue(Dominator.result(), Default); 644 645 Term->setCondition(PhiInserter.GetValueInMiddleOfBlock(Parent)); 646 } 647 } 648 } 649 650 /// Simplify any inverted conditions that were built by buildConditions. 651 void StructurizeCFG::simplifyConditions() { 652 SmallVector<Instruction *> InstToErase; 653 for (auto &I : concat<PredMap::value_type>(Predicates, LoopPreds)) { 654 auto &Preds = I.second; 655 for (auto &J : Preds) { 656 Value *Cond = J.second.first; 657 Instruction *Inverted; 658 if (match(Cond, m_Not(m_OneUse(m_Instruction(Inverted)))) && 659 !Cond->use_empty()) { 660 if (auto *InvertedCmp = dyn_cast<CmpInst>(Inverted)) { 661 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate()); 662 Cond->replaceAllUsesWith(InvertedCmp); 663 InstToErase.push_back(cast<Instruction>(Cond)); 664 } 665 } 666 } 667 } 668 for (auto *I : InstToErase) 669 I->eraseFromParent(); 670 } 671 672 /// Remove all PHI values coming from "From" into "To" and remember 673 /// them in DeletedPhis 674 void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) { 675 PhiMap &Map = DeletedPhis[To]; 676 for (PHINode &Phi : To->phis()) { 677 bool Recorded = false; 678 while (Phi.getBasicBlockIndex(From) != -1) { 679 Value *Deleted = Phi.removeIncomingValue(From, false); 680 Map[&Phi].push_back(std::make_pair(From, Deleted)); 681 if (!Recorded) { 682 AffectedPhis.push_back(&Phi); 683 Recorded = true; 684 } 685 } 686 } 687 } 688 689 /// Add a dummy PHI value as soon as we knew the new predecessor 690 void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) { 691 for (PHINode &Phi : To->phis()) { 692 Value *Undef = UndefValue::get(Phi.getType()); 693 Phi.addIncoming(Undef, From); 694 } 695 AddedPhis[To].push_back(From); 696 } 697 698 /// When we are reconstructing a PHI inside \p PHIBlock with incoming values 699 /// from predecessors \p Incomings, we have a chance to mark the available value 700 /// from some blocks as undefined. The function will find out all such blocks 701 /// and return in \p UndefBlks. 702 void StructurizeCFG::findUndefBlocks( 703 BasicBlock *PHIBlock, const SmallSet<BasicBlock *, 8> &Incomings, 704 SmallVector<BasicBlock *> &UndefBlks) const { 705 // We may get a post-structured CFG like below: 706 // 707 // | P1 708 // |/ 709 // F1 710 // |\ 711 // | N 712 // |/ 713 // F2 714 // |\ 715 // | P2 716 // |/ 717 // F3 718 // |\ 719 // B 720 // 721 // B is the block that has a PHI being reconstructed. P1/P2 are predecessors 722 // of B before structurization. F1/F2/F3 are flow blocks inserted during 723 // structurization process. Block N is not a predecessor of B before 724 // structurization, but are placed between the predecessors(P1/P2) of B after 725 // structurization. This usually means that threads went to N never take the 726 // path N->F2->F3->B. For example, the threads take the branch F1->N may 727 // always take the branch F2->P2. So, when we are reconstructing a PHI 728 // originally in B, we can safely say the incoming value from N is undefined. 729 SmallSet<BasicBlock *, 8> VisitedBlock; 730 SmallVector<BasicBlock *, 8> Stack; 731 if (PHIBlock == ParentRegion->getExit()) { 732 for (auto P : predecessors(PHIBlock)) { 733 if (ParentRegion->contains(P)) 734 Stack.push_back(P); 735 } 736 } else { 737 append_range(Stack, predecessors(PHIBlock)); 738 } 739 740 // Do a backward traversal over the CFG, and stop further searching if 741 // the block is not a Flow. If a block is neither flow block nor the 742 // incoming predecessor, then the incoming value from the block is 743 // undefined value for the PHI being reconstructed. 744 while (!Stack.empty()) { 745 BasicBlock *Current = Stack.pop_back_val(); 746 if (!VisitedBlock.insert(Current).second) 747 continue; 748 749 if (FlowSet.contains(Current)) { 750 for (auto P : predecessors(Current)) 751 Stack.push_back(P); 752 } else if (!Incomings.contains(Current)) { 753 UndefBlks.push_back(Current); 754 } 755 } 756 } 757 758 /// Add the real PHI value as soon as everything is set up 759 void StructurizeCFG::setPhiValues() { 760 SmallVector<PHINode *, 8> InsertedPhis; 761 SSAUpdater Updater(&InsertedPhis); 762 for (const auto &AddedPhi : AddedPhis) { 763 BasicBlock *To = AddedPhi.first; 764 const BBVector &From = AddedPhi.second; 765 766 if (!DeletedPhis.count(To)) 767 continue; 768 769 SmallVector<BasicBlock *> UndefBlks; 770 bool CachedUndefs = false; 771 PhiMap &Map = DeletedPhis[To]; 772 for (const auto &PI : Map) { 773 PHINode *Phi = PI.first; 774 Value *Undef = UndefValue::get(Phi->getType()); 775 Updater.Initialize(Phi->getType(), ""); 776 Updater.AddAvailableValue(&Func->getEntryBlock(), Undef); 777 Updater.AddAvailableValue(To, Undef); 778 779 SmallSet<BasicBlock *, 8> Incomings; 780 SmallVector<BasicBlock *> ConstantPreds; 781 for (const auto &VI : PI.second) { 782 Incomings.insert(VI.first); 783 Updater.AddAvailableValue(VI.first, VI.second); 784 if (isa<Constant>(VI.second)) 785 ConstantPreds.push_back(VI.first); 786 } 787 788 if (!CachedUndefs) { 789 findUndefBlocks(To, Incomings, UndefBlks); 790 CachedUndefs = true; 791 } 792 793 for (auto UB : UndefBlks) { 794 // If this undef block is dominated by any predecessor(before 795 // structurization) of reconstructed PHI with constant incoming value, 796 // don't mark the available value as undefined. Setting undef to such 797 // block will stop us from getting optimal phi insertion. 798 if (any_of(ConstantPreds, 799 [&](BasicBlock *CP) { return DT->dominates(CP, UB); })) 800 continue; 801 Updater.AddAvailableValue(UB, Undef); 802 } 803 804 for (BasicBlock *FI : From) 805 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI)); 806 AffectedPhis.push_back(Phi); 807 } 808 809 DeletedPhis.erase(To); 810 } 811 assert(DeletedPhis.empty()); 812 813 AffectedPhis.append(InsertedPhis.begin(), InsertedPhis.end()); 814 } 815 816 void StructurizeCFG::simplifyAffectedPhis() { 817 bool Changed; 818 do { 819 Changed = false; 820 SimplifyQuery Q(Func->getDataLayout()); 821 Q.DT = DT; 822 // Setting CanUseUndef to true might extend value liveness, set it to false 823 // to achieve better register pressure. 824 Q.CanUseUndef = false; 825 for (WeakVH VH : AffectedPhis) { 826 if (auto Phi = dyn_cast_or_null<PHINode>(VH)) { 827 if (auto NewValue = simplifyInstruction(Phi, Q)) { 828 Phi->replaceAllUsesWith(NewValue); 829 Phi->eraseFromParent(); 830 Changed = true; 831 } 832 } 833 } 834 } while (Changed); 835 } 836 837 /// Remove phi values from all successors and then remove the terminator. 838 void StructurizeCFG::killTerminator(BasicBlock *BB) { 839 Instruction *Term = BB->getTerminator(); 840 if (!Term) 841 return; 842 843 for (BasicBlock *Succ : successors(BB)) 844 delPhiValues(BB, Succ); 845 846 Term->eraseFromParent(); 847 } 848 849 /// Let node exit(s) point to NewExit 850 void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit, 851 bool IncludeDominator) { 852 if (Node->isSubRegion()) { 853 Region *SubRegion = Node->getNodeAs<Region>(); 854 BasicBlock *OldExit = SubRegion->getExit(); 855 BasicBlock *Dominator = nullptr; 856 857 // Find all the edges from the sub region to the exit. 858 // We use make_early_inc_range here because we modify BB's terminator. 859 for (BasicBlock *BB : llvm::make_early_inc_range(predecessors(OldExit))) { 860 if (!SubRegion->contains(BB)) 861 continue; 862 863 // Modify the edges to point to the new exit 864 delPhiValues(BB, OldExit); 865 BB->getTerminator()->replaceUsesOfWith(OldExit, NewExit); 866 addPhiValues(BB, NewExit); 867 868 // Find the new dominator (if requested) 869 if (IncludeDominator) { 870 if (!Dominator) 871 Dominator = BB; 872 else 873 Dominator = DT->findNearestCommonDominator(Dominator, BB); 874 } 875 } 876 877 // Change the dominator (if requested) 878 if (Dominator) 879 DT->changeImmediateDominator(NewExit, Dominator); 880 881 // Update the region info 882 SubRegion->replaceExit(NewExit); 883 } else { 884 BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 885 killTerminator(BB); 886 BranchInst *Br = BranchInst::Create(NewExit, BB); 887 Br->setDebugLoc(TermDL[BB]); 888 addPhiValues(BB, NewExit); 889 if (IncludeDominator) 890 DT->changeImmediateDominator(NewExit, BB); 891 } 892 } 893 894 /// Create a new flow node and update dominator tree and region info 895 BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) { 896 LLVMContext &Context = Func->getContext(); 897 BasicBlock *Insert = Order.empty() ? ParentRegion->getExit() : 898 Order.back()->getEntry(); 899 BasicBlock *Flow = BasicBlock::Create(Context, FlowBlockName, 900 Func, Insert); 901 FlowSet.insert(Flow); 902 903 // use a temporary variable to avoid a use-after-free if the map's storage is 904 // reallocated 905 DebugLoc DL = TermDL[Dominator]; 906 TermDL[Flow] = std::move(DL); 907 908 DT->addNewBlock(Flow, Dominator); 909 ParentRegion->getRegionInfo()->setRegionFor(Flow, ParentRegion); 910 return Flow; 911 } 912 913 /// Create a new or reuse the previous node as flow node 914 BasicBlock *StructurizeCFG::needPrefix(bool NeedEmpty) { 915 BasicBlock *Entry = PrevNode->getEntry(); 916 917 if (!PrevNode->isSubRegion()) { 918 killTerminator(Entry); 919 if (!NeedEmpty || Entry->getFirstInsertionPt() == Entry->end()) 920 return Entry; 921 } 922 923 // create a new flow node 924 BasicBlock *Flow = getNextFlow(Entry); 925 926 // and wire it up 927 changeExit(PrevNode, Flow, true); 928 PrevNode = ParentRegion->getBBNode(Flow); 929 return Flow; 930 } 931 932 /// Returns the region exit if possible, otherwise just a new flow node 933 BasicBlock *StructurizeCFG::needPostfix(BasicBlock *Flow, 934 bool ExitUseAllowed) { 935 if (!Order.empty() || !ExitUseAllowed) 936 return getNextFlow(Flow); 937 938 BasicBlock *Exit = ParentRegion->getExit(); 939 DT->changeImmediateDominator(Exit, Flow); 940 addPhiValues(Flow, Exit); 941 return Exit; 942 } 943 944 /// Set the previous node 945 void StructurizeCFG::setPrevNode(BasicBlock *BB) { 946 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB) 947 : nullptr; 948 } 949 950 /// Does BB dominate all the predicates of Node? 951 bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) { 952 BBPredicates &Preds = Predicates[Node->getEntry()]; 953 return llvm::all_of(Preds, 954 [&](std::pair<BasicBlock *, ValueWeightPair> Pred) { 955 return DT->dominates(BB, Pred.first); 956 }); 957 } 958 959 /// Can we predict that this node will always be called? 960 bool StructurizeCFG::isPredictableTrue(RegionNode *Node) { 961 BBPredicates &Preds = Predicates[Node->getEntry()]; 962 bool Dominated = false; 963 964 // Regionentry is always true 965 if (!PrevNode) 966 return true; 967 968 for (std::pair<BasicBlock *, ValueWeightPair> Pred : Preds) { 969 BasicBlock *BB = Pred.first; 970 Value *V = Pred.second.first; 971 972 if (V != BoolTrue) 973 return false; 974 975 if (!Dominated && DT->dominates(BB, PrevNode->getEntry())) 976 Dominated = true; 977 } 978 979 // TODO: The dominator check is too strict 980 return Dominated; 981 } 982 983 /// Take one node from the order vector and wire it up 984 void StructurizeCFG::wireFlow(bool ExitUseAllowed, 985 BasicBlock *LoopEnd) { 986 RegionNode *Node = Order.pop_back_val(); 987 Visited.insert(Node->getEntry()); 988 989 if (isPredictableTrue(Node)) { 990 // Just a linear flow 991 if (PrevNode) { 992 changeExit(PrevNode, Node->getEntry(), true); 993 } 994 PrevNode = Node; 995 } else { 996 // Insert extra prefix node (or reuse last one) 997 BasicBlock *Flow = needPrefix(false); 998 999 // Insert extra postfix node (or use exit instead) 1000 BasicBlock *Entry = Node->getEntry(); 1001 BasicBlock *Next = needPostfix(Flow, ExitUseAllowed); 1002 1003 // let it point to entry and next block 1004 BranchInst *Br = BranchInst::Create(Entry, Next, BoolPoison, Flow); 1005 Br->setDebugLoc(TermDL[Flow]); 1006 Conditions.push_back(Br); 1007 addPhiValues(Flow, Entry); 1008 DT->changeImmediateDominator(Entry, Flow); 1009 1010 PrevNode = Node; 1011 while (!Order.empty() && !Visited.count(LoopEnd) && 1012 dominatesPredicates(Entry, Order.back())) { 1013 handleLoops(false, LoopEnd); 1014 } 1015 1016 changeExit(PrevNode, Next, false); 1017 setPrevNode(Next); 1018 } 1019 } 1020 1021 void StructurizeCFG::handleLoops(bool ExitUseAllowed, 1022 BasicBlock *LoopEnd) { 1023 RegionNode *Node = Order.back(); 1024 BasicBlock *LoopStart = Node->getEntry(); 1025 1026 if (!Loops.count(LoopStart)) { 1027 wireFlow(ExitUseAllowed, LoopEnd); 1028 return; 1029 } 1030 1031 if (!isPredictableTrue(Node)) 1032 LoopStart = needPrefix(true); 1033 1034 LoopEnd = Loops[Node->getEntry()]; 1035 wireFlow(false, LoopEnd); 1036 while (!Visited.count(LoopEnd)) { 1037 handleLoops(false, LoopEnd); 1038 } 1039 1040 assert(LoopStart != &LoopStart->getParent()->getEntryBlock()); 1041 1042 // Create an extra loop end node 1043 LoopEnd = needPrefix(false); 1044 BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed); 1045 BranchInst *Br = BranchInst::Create(Next, LoopStart, BoolPoison, LoopEnd); 1046 Br->setDebugLoc(TermDL[LoopEnd]); 1047 LoopConds.push_back(Br); 1048 addPhiValues(LoopEnd, LoopStart); 1049 setPrevNode(Next); 1050 } 1051 1052 /// After this function control flow looks like it should be, but 1053 /// branches and PHI nodes only have undefined conditions. 1054 void StructurizeCFG::createFlow() { 1055 BasicBlock *Exit = ParentRegion->getExit(); 1056 bool EntryDominatesExit = DT->dominates(ParentRegion->getEntry(), Exit); 1057 1058 AffectedPhis.clear(); 1059 DeletedPhis.clear(); 1060 AddedPhis.clear(); 1061 Conditions.clear(); 1062 LoopConds.clear(); 1063 1064 PrevNode = nullptr; 1065 Visited.clear(); 1066 1067 while (!Order.empty()) { 1068 handleLoops(EntryDominatesExit, nullptr); 1069 } 1070 1071 if (PrevNode) 1072 changeExit(PrevNode, Exit, EntryDominatesExit); 1073 else 1074 assert(EntryDominatesExit); 1075 } 1076 1077 /// Handle a rare case where the disintegrated nodes instructions 1078 /// no longer dominate all their uses. Not sure if this is really necessary 1079 void StructurizeCFG::rebuildSSA() { 1080 SSAUpdater Updater; 1081 for (BasicBlock *BB : ParentRegion->blocks()) 1082 for (Instruction &I : *BB) { 1083 bool Initialized = false; 1084 // We may modify the use list as we iterate over it, so we use 1085 // make_early_inc_range. 1086 for (Use &U : llvm::make_early_inc_range(I.uses())) { 1087 Instruction *User = cast<Instruction>(U.getUser()); 1088 if (User->getParent() == BB) { 1089 continue; 1090 } else if (PHINode *UserPN = dyn_cast<PHINode>(User)) { 1091 if (UserPN->getIncomingBlock(U) == BB) 1092 continue; 1093 } 1094 1095 if (DT->dominates(&I, User)) 1096 continue; 1097 1098 if (!Initialized) { 1099 Value *Undef = UndefValue::get(I.getType()); 1100 Updater.Initialize(I.getType(), ""); 1101 Updater.AddAvailableValue(&Func->getEntryBlock(), Undef); 1102 Updater.AddAvailableValue(BB, &I); 1103 Initialized = true; 1104 } 1105 Updater.RewriteUseAfterInsertions(U); 1106 } 1107 } 1108 } 1109 1110 static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, 1111 const UniformityInfo &UA) { 1112 // Bool for if all sub-regions are uniform. 1113 bool SubRegionsAreUniform = true; 1114 // Count of how many direct children are conditional. 1115 unsigned ConditionalDirectChildren = 0; 1116 1117 for (auto *E : R->elements()) { 1118 if (!E->isSubRegion()) { 1119 auto Br = dyn_cast<BranchInst>(E->getEntry()->getTerminator()); 1120 if (!Br || !Br->isConditional()) 1121 continue; 1122 1123 if (!UA.isUniform(Br)) 1124 return false; 1125 1126 // One of our direct children is conditional. 1127 ConditionalDirectChildren++; 1128 1129 LLVM_DEBUG(dbgs() << "BB: " << Br->getParent()->getName() 1130 << " has uniform terminator\n"); 1131 } else { 1132 // Explicitly refuse to treat regions as uniform if they have non-uniform 1133 // subregions. We cannot rely on UniformityAnalysis for branches in 1134 // subregions because those branches may have been removed and re-created, 1135 // so we look for our metadata instead. 1136 // 1137 // Warning: It would be nice to treat regions as uniform based only on 1138 // their direct child basic blocks' terminators, regardless of whether 1139 // subregions are uniform or not. However, this requires a very careful 1140 // look at SIAnnotateControlFlow to make sure nothing breaks there. 1141 for (auto *BB : E->getNodeAs<Region>()->blocks()) { 1142 auto Br = dyn_cast<BranchInst>(BB->getTerminator()); 1143 if (!Br || !Br->isConditional()) 1144 continue; 1145 1146 if (!Br->getMetadata(UniformMDKindID)) { 1147 // Early exit if we cannot have relaxed uniform regions. 1148 if (!RelaxedUniformRegions) 1149 return false; 1150 1151 SubRegionsAreUniform = false; 1152 break; 1153 } 1154 } 1155 } 1156 } 1157 1158 // Our region is uniform if: 1159 // 1. All conditional branches that are direct children are uniform (checked 1160 // above). 1161 // 2. And either: 1162 // a. All sub-regions are uniform. 1163 // b. There is one or less conditional branches among the direct children. 1164 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1); 1165 } 1166 1167 void StructurizeCFG::init(Region *R) { 1168 LLVMContext &Context = R->getEntry()->getContext(); 1169 1170 Boolean = Type::getInt1Ty(Context); 1171 BoolTrue = ConstantInt::getTrue(Context); 1172 BoolFalse = ConstantInt::getFalse(Context); 1173 BoolPoison = PoisonValue::get(Boolean); 1174 1175 this->UA = nullptr; 1176 } 1177 1178 bool StructurizeCFG::makeUniformRegion(Region *R, UniformityInfo &UA) { 1179 if (R->isTopLevelRegion()) 1180 return false; 1181 1182 this->UA = &UA; 1183 1184 // TODO: We could probably be smarter here with how we handle sub-regions. 1185 // We currently rely on the fact that metadata is set by earlier invocations 1186 // of the pass on sub-regions, and that this metadata doesn't get lost -- 1187 // but we shouldn't rely on metadata for correctness! 1188 unsigned UniformMDKindID = 1189 R->getEntry()->getContext().getMDKindID("structurizecfg.uniform"); 1190 1191 if (hasOnlyUniformBranches(R, UniformMDKindID, UA)) { 1192 LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R 1193 << '\n'); 1194 1195 // Mark all direct child block terminators as having been treated as 1196 // uniform. To account for a possible future in which non-uniform 1197 // sub-regions are treated more cleverly, indirect children are not 1198 // marked as uniform. 1199 MDNode *MD = MDNode::get(R->getEntry()->getParent()->getContext(), {}); 1200 for (RegionNode *E : R->elements()) { 1201 if (E->isSubRegion()) 1202 continue; 1203 1204 if (Instruction *Term = E->getEntry()->getTerminator()) 1205 Term->setMetadata(UniformMDKindID, MD); 1206 } 1207 1208 return true; 1209 } 1210 return false; 1211 } 1212 1213 /// Run the transformation for each region found 1214 bool StructurizeCFG::run(Region *R, DominatorTree *DT) { 1215 if (R->isTopLevelRegion()) 1216 return false; 1217 1218 this->DT = DT; 1219 1220 Func = R->getEntry()->getParent(); 1221 assert(hasOnlySimpleTerminator(*Func) && "Unsupported block terminator."); 1222 1223 ParentRegion = R; 1224 1225 orderNodes(); 1226 collectInfos(); 1227 createFlow(); 1228 insertConditions(false); 1229 insertConditions(true); 1230 setPhiValues(); 1231 simplifyConditions(); 1232 simplifyAffectedPhis(); 1233 rebuildSSA(); 1234 1235 // Cleanup 1236 Order.clear(); 1237 Visited.clear(); 1238 DeletedPhis.clear(); 1239 AddedPhis.clear(); 1240 Predicates.clear(); 1241 Conditions.clear(); 1242 Loops.clear(); 1243 LoopPreds.clear(); 1244 LoopConds.clear(); 1245 FlowSet.clear(); 1246 TermDL.clear(); 1247 1248 return true; 1249 } 1250 1251 Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) { 1252 return new StructurizeCFGLegacyPass(SkipUniformRegions); 1253 } 1254 1255 static void addRegionIntoQueue(Region &R, std::vector<Region *> &Regions) { 1256 Regions.push_back(&R); 1257 for (const auto &E : R) 1258 addRegionIntoQueue(*E, Regions); 1259 } 1260 1261 StructurizeCFGPass::StructurizeCFGPass(bool SkipUniformRegions_) 1262 : SkipUniformRegions(SkipUniformRegions_) { 1263 if (ForceSkipUniformRegions.getNumOccurrences()) 1264 SkipUniformRegions = ForceSkipUniformRegions.getValue(); 1265 } 1266 1267 void StructurizeCFGPass::printPipeline( 1268 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 1269 static_cast<PassInfoMixin<StructurizeCFGPass> *>(this)->printPipeline( 1270 OS, MapClassName2PassName); 1271 if (SkipUniformRegions) 1272 OS << "<skip-uniform-regions>"; 1273 } 1274 1275 PreservedAnalyses StructurizeCFGPass::run(Function &F, 1276 FunctionAnalysisManager &AM) { 1277 1278 bool Changed = false; 1279 DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F); 1280 auto &RI = AM.getResult<RegionInfoAnalysis>(F); 1281 1282 UniformityInfo *UI = nullptr; 1283 if (SkipUniformRegions) 1284 UI = &AM.getResult<UniformityInfoAnalysis>(F); 1285 1286 std::vector<Region *> Regions; 1287 addRegionIntoQueue(*RI.getTopLevelRegion(), Regions); 1288 while (!Regions.empty()) { 1289 Region *R = Regions.back(); 1290 Regions.pop_back(); 1291 1292 StructurizeCFG SCFG; 1293 SCFG.init(R); 1294 1295 if (SkipUniformRegions && SCFG.makeUniformRegion(R, *UI)) { 1296 Changed = true; // May have added metadata. 1297 continue; 1298 } 1299 1300 Changed |= SCFG.run(R, DT); 1301 } 1302 if (!Changed) 1303 return PreservedAnalyses::all(); 1304 PreservedAnalyses PA; 1305 PA.preserve<DominatorTreeAnalysis>(); 1306 return PA; 1307 } 1308