10b57cec5SDimitry Andric //===- StructurizeCFG.cpp -------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/StructurizeCFG.h" 100b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 110b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h" 125ffd83dbSDimitry Andric #include "llvm/ADT/SCCIterator.h" 130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 140b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/SmallSet.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 180b57cec5SDimitry Andric #include "llvm/Analysis/RegionInfo.h" 190b57cec5SDimitry Andric #include "llvm/Analysis/RegionIterator.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/RegionPass.h" 2106c3fb27SDimitry Andric #include "llvm/Analysis/UniformityAnalysis.h" 220b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 230b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 260b57cec5SDimitry Andric #include "llvm/IR/Function.h" 270b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 280b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 290b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 300b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 31e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 320b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h" 330b57cec5SDimitry Andric #include "llvm/IR/Type.h" 340b57cec5SDimitry Andric #include "llvm/IR/Use.h" 350b57cec5SDimitry Andric #include "llvm/IR/Value.h" 365ffd83dbSDimitry Andric #include "llvm/IR/ValueHandle.h" 37480093f4SDimitry Andric #include "llvm/InitializePasses.h" 380b57cec5SDimitry Andric #include "llvm/Pass.h" 390b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 40480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 410b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 420b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 430b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 440b57cec5SDimitry Andric #include "llvm/Transforms/Utils.h" 455f757f3fSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 465ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/Local.h" 470b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SSAUpdater.h" 480b57cec5SDimitry Andric #include <algorithm> 490b57cec5SDimitry Andric #include <cassert> 500b57cec5SDimitry Andric #include <utility> 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric using namespace llvm; 530b57cec5SDimitry Andric using namespace llvm::PatternMatch; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #define DEBUG_TYPE "structurizecfg" 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // The name for newly created blocks. 58e8d8bef9SDimitry Andric const char FlowBlockName[] = "Flow"; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric namespace { 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric static cl::opt<bool> ForceSkipUniformRegions( 630b57cec5SDimitry Andric "structurizecfg-skip-uniform-regions", 640b57cec5SDimitry Andric cl::Hidden, 650b57cec5SDimitry Andric cl::desc("Force whether the StructurizeCFG pass skips uniform regions"), 660b57cec5SDimitry Andric cl::init(false)); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric static cl::opt<bool> 690b57cec5SDimitry Andric RelaxedUniformRegions("structurizecfg-relaxed-uniform-regions", cl::Hidden, 700b57cec5SDimitry Andric cl::desc("Allow relaxed uniform region checks"), 718bcb0991SDimitry Andric cl::init(true)); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // Definition of the complex types used in this pass. 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric using BBValuePair = std::pair<BasicBlock *, Value *>; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric using RNVector = SmallVector<RegionNode *, 8>; 780b57cec5SDimitry Andric using BBVector = SmallVector<BasicBlock *, 8>; 790b57cec5SDimitry Andric using BranchVector = SmallVector<BranchInst *, 8>; 800b57cec5SDimitry Andric using BBValueVector = SmallVector<BBValuePair, 2>; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric using BBSet = SmallPtrSet<BasicBlock *, 8>; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric using PhiMap = MapVector<PHINode *, BBValueVector>; 850b57cec5SDimitry Andric using BB2BBVecMap = MapVector<BasicBlock *, BBVector>; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric using BBPhiMap = DenseMap<BasicBlock *, PhiMap>; 880b57cec5SDimitry Andric using BBPredicates = DenseMap<BasicBlock *, Value *>; 890b57cec5SDimitry Andric using PredMap = DenseMap<BasicBlock *, BBPredicates>; 900b57cec5SDimitry Andric using BB2BBMap = DenseMap<BasicBlock *, BasicBlock *>; 910b57cec5SDimitry Andric 92bdd1243dSDimitry Andric using BranchDebugLocMap = DenseMap<BasicBlock *, DebugLoc>; 93bdd1243dSDimitry Andric 945ffd83dbSDimitry Andric // A traits type that is intended to be used in graph algorithms. The graph 955ffd83dbSDimitry Andric // traits starts at an entry node, and traverses the RegionNodes that are in 965ffd83dbSDimitry Andric // the Nodes set. 975ffd83dbSDimitry Andric struct SubGraphTraits { 985ffd83dbSDimitry Andric using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>; 995ffd83dbSDimitry Andric using BaseSuccIterator = GraphTraits<RegionNode *>::ChildIteratorType; 1005ffd83dbSDimitry Andric 1015ffd83dbSDimitry Andric // This wraps a set of Nodes into the iterator, so we know which edges to 1025ffd83dbSDimitry Andric // filter out. 1035ffd83dbSDimitry Andric class WrappedSuccIterator 1045ffd83dbSDimitry Andric : public iterator_adaptor_base< 1055ffd83dbSDimitry Andric WrappedSuccIterator, BaseSuccIterator, 1065ffd83dbSDimitry Andric typename std::iterator_traits<BaseSuccIterator>::iterator_category, 1075ffd83dbSDimitry Andric NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> { 1085ffd83dbSDimitry Andric SmallDenseSet<RegionNode *> *Nodes; 1095ffd83dbSDimitry Andric 1105ffd83dbSDimitry Andric public: 1115ffd83dbSDimitry Andric WrappedSuccIterator(BaseSuccIterator It, SmallDenseSet<RegionNode *> *Nodes) 1125ffd83dbSDimitry Andric : iterator_adaptor_base(It), Nodes(Nodes) {} 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric NodeRef operator*() const { return {*I, Nodes}; } 1155ffd83dbSDimitry Andric }; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric static bool filterAll(const NodeRef &N) { return true; } 1185ffd83dbSDimitry Andric static bool filterSet(const NodeRef &N) { return N.second->count(N.first); } 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric using ChildIteratorType = 1215ffd83dbSDimitry Andric filter_iterator<WrappedSuccIterator, bool (*)(const NodeRef &)>; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric static NodeRef getEntryNode(Region *R) { 1245ffd83dbSDimitry Andric return {GraphTraits<Region *>::getEntryNode(R), nullptr}; 1255ffd83dbSDimitry Andric } 1265ffd83dbSDimitry Andric 1275ffd83dbSDimitry Andric static NodeRef getEntryNode(NodeRef N) { return N; } 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric static iterator_range<ChildIteratorType> children(const NodeRef &N) { 1305ffd83dbSDimitry Andric auto *filter = N.second ? &filterSet : &filterAll; 1315ffd83dbSDimitry Andric return make_filter_range( 1325ffd83dbSDimitry Andric make_range<WrappedSuccIterator>( 1335ffd83dbSDimitry Andric {GraphTraits<RegionNode *>::child_begin(N.first), N.second}, 1345ffd83dbSDimitry Andric {GraphTraits<RegionNode *>::child_end(N.first), N.second}), 1355ffd83dbSDimitry Andric filter); 1365ffd83dbSDimitry Andric } 1375ffd83dbSDimitry Andric 1385ffd83dbSDimitry Andric static ChildIteratorType child_begin(const NodeRef &N) { 1395ffd83dbSDimitry Andric return children(N).begin(); 1405ffd83dbSDimitry Andric } 1415ffd83dbSDimitry Andric 1425ffd83dbSDimitry Andric static ChildIteratorType child_end(const NodeRef &N) { 1435ffd83dbSDimitry Andric return children(N).end(); 1445ffd83dbSDimitry Andric } 1455ffd83dbSDimitry Andric }; 1465ffd83dbSDimitry Andric 1470b57cec5SDimitry Andric /// Finds the nearest common dominator of a set of BasicBlocks. 1480b57cec5SDimitry Andric /// 1490b57cec5SDimitry Andric /// For every BB you add to the set, you can specify whether we "remember" the 1500b57cec5SDimitry Andric /// block. When you get the common dominator, you can also ask whether it's one 1510b57cec5SDimitry Andric /// of the blocks we remembered. 1520b57cec5SDimitry Andric class NearestCommonDominator { 1530b57cec5SDimitry Andric DominatorTree *DT; 1540b57cec5SDimitry Andric BasicBlock *Result = nullptr; 1550b57cec5SDimitry Andric bool ResultIsRemembered = false; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric /// Add BB to the resulting dominator. 1580b57cec5SDimitry Andric void addBlock(BasicBlock *BB, bool Remember) { 1590b57cec5SDimitry Andric if (!Result) { 1600b57cec5SDimitry Andric Result = BB; 1610b57cec5SDimitry Andric ResultIsRemembered = Remember; 1620b57cec5SDimitry Andric return; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric BasicBlock *NewResult = DT->findNearestCommonDominator(Result, BB); 1660b57cec5SDimitry Andric if (NewResult != Result) 1670b57cec5SDimitry Andric ResultIsRemembered = false; 1680b57cec5SDimitry Andric if (NewResult == BB) 1690b57cec5SDimitry Andric ResultIsRemembered |= Remember; 1700b57cec5SDimitry Andric Result = NewResult; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric public: 1740b57cec5SDimitry Andric explicit NearestCommonDominator(DominatorTree *DomTree) : DT(DomTree) {} 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void addBlock(BasicBlock *BB) { 1770b57cec5SDimitry Andric addBlock(BB, /* Remember = */ false); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric void addAndRememberBlock(BasicBlock *BB) { 1810b57cec5SDimitry Andric addBlock(BB, /* Remember = */ true); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric /// Get the nearest common dominator of all the BBs added via addBlock() and 1850b57cec5SDimitry Andric /// addAndRememberBlock(). 1860b57cec5SDimitry Andric BasicBlock *result() { return Result; } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric /// Is the BB returned by getResult() one of the blocks we added to the set 1890b57cec5SDimitry Andric /// with addAndRememberBlock()? 1900b57cec5SDimitry Andric bool resultIsRememberedBlock() { return ResultIsRemembered; } 1910b57cec5SDimitry Andric }; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric /// Transforms the control flow graph on one single entry/exit region 1940b57cec5SDimitry Andric /// at a time. 1950b57cec5SDimitry Andric /// 1960b57cec5SDimitry Andric /// After the transform all "If"/"Then"/"Else" style control flow looks like 1970b57cec5SDimitry Andric /// this: 1980b57cec5SDimitry Andric /// 1990b57cec5SDimitry Andric /// \verbatim 2000b57cec5SDimitry Andric /// 1 2010b57cec5SDimitry Andric /// || 2020b57cec5SDimitry Andric /// | | 2030b57cec5SDimitry Andric /// 2 | 2040b57cec5SDimitry Andric /// | / 2050b57cec5SDimitry Andric /// |/ 2060b57cec5SDimitry Andric /// 3 2070b57cec5SDimitry Andric /// || Where: 2080b57cec5SDimitry Andric /// | | 1 = "If" block, calculates the condition 2090b57cec5SDimitry Andric /// 4 | 2 = "Then" subregion, runs if the condition is true 2100b57cec5SDimitry Andric /// | / 3 = "Flow" blocks, newly inserted flow blocks, rejoins the flow 2110b57cec5SDimitry Andric /// |/ 4 = "Else" optional subregion, runs if the condition is false 2120b57cec5SDimitry Andric /// 5 5 = "End" block, also rejoins the control flow 2130b57cec5SDimitry Andric /// \endverbatim 2140b57cec5SDimitry Andric /// 2150b57cec5SDimitry Andric /// Control flow is expressed as a branch where the true exit goes into the 2160b57cec5SDimitry Andric /// "Then"/"Else" region, while the false exit skips the region 2170b57cec5SDimitry Andric /// The condition for the optional "Else" region is expressed as a PHI node. 2180b57cec5SDimitry Andric /// The incoming values of the PHI node are true for the "If" edge and false 2190b57cec5SDimitry Andric /// for the "Then" edge. 2200b57cec5SDimitry Andric /// 2210b57cec5SDimitry Andric /// Additionally to that even complicated loops look like this: 2220b57cec5SDimitry Andric /// 2230b57cec5SDimitry Andric /// \verbatim 2240b57cec5SDimitry Andric /// 1 2250b57cec5SDimitry Andric /// || 2260b57cec5SDimitry Andric /// | | 2270b57cec5SDimitry Andric /// 2 ^ Where: 2280b57cec5SDimitry Andric /// | / 1 = "Entry" block 2290b57cec5SDimitry Andric /// |/ 2 = "Loop" optional subregion, with all exits at "Flow" block 2300b57cec5SDimitry Andric /// 3 3 = "Flow" block, with back edge to entry block 2310b57cec5SDimitry Andric /// | 2320b57cec5SDimitry Andric /// \endverbatim 2330b57cec5SDimitry Andric /// 2340b57cec5SDimitry Andric /// The back edge of the "Flow" block is always on the false side of the branch 2350b57cec5SDimitry Andric /// while the true side continues the general flow. So the loop condition 2360b57cec5SDimitry Andric /// consist of a network of PHI nodes where the true incoming values expresses 2370b57cec5SDimitry Andric /// breaks and the false values expresses continue states. 2380b57cec5SDimitry Andric 239e8d8bef9SDimitry Andric class StructurizeCFG { 2400b57cec5SDimitry Andric Type *Boolean; 2410b57cec5SDimitry Andric ConstantInt *BoolTrue; 2420b57cec5SDimitry Andric ConstantInt *BoolFalse; 24306c3fb27SDimitry Andric Value *BoolPoison; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric Function *Func; 2460b57cec5SDimitry Andric Region *ParentRegion; 2470b57cec5SDimitry Andric 24806c3fb27SDimitry Andric UniformityInfo *UA = nullptr; 2490b57cec5SDimitry Andric DominatorTree *DT; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric SmallVector<RegionNode *, 8> Order; 2520b57cec5SDimitry Andric BBSet Visited; 253bdd1243dSDimitry Andric BBSet FlowSet; 2540b57cec5SDimitry Andric 2555ffd83dbSDimitry Andric SmallVector<WeakVH, 8> AffectedPhis; 2560b57cec5SDimitry Andric BBPhiMap DeletedPhis; 2570b57cec5SDimitry Andric BB2BBVecMap AddedPhis; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric PredMap Predicates; 2600b57cec5SDimitry Andric BranchVector Conditions; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric BB2BBMap Loops; 2630b57cec5SDimitry Andric PredMap LoopPreds; 2640b57cec5SDimitry Andric BranchVector LoopConds; 2650b57cec5SDimitry Andric 266bdd1243dSDimitry Andric BranchDebugLocMap TermDL; 267bdd1243dSDimitry Andric 2680b57cec5SDimitry Andric RegionNode *PrevNode; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric void orderNodes(); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric void analyzeLoops(RegionNode *N); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric Value *buildCondition(BranchInst *Term, unsigned Idx, bool Invert); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric void gatherPredicates(RegionNode *N); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric void collectInfos(); 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric void insertConditions(bool Loops); 2810b57cec5SDimitry Andric 2821fd87a68SDimitry Andric void simplifyConditions(); 2831fd87a68SDimitry Andric 2840b57cec5SDimitry Andric void delPhiValues(BasicBlock *From, BasicBlock *To); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric void addPhiValues(BasicBlock *From, BasicBlock *To); 2870b57cec5SDimitry Andric 288bdd1243dSDimitry Andric void findUndefBlocks(BasicBlock *PHIBlock, 289bdd1243dSDimitry Andric const SmallSet<BasicBlock *, 8> &Incomings, 290bdd1243dSDimitry Andric SmallVector<BasicBlock *> &UndefBlks) const; 2910b57cec5SDimitry Andric void setPhiValues(); 2920b57cec5SDimitry Andric 2935ffd83dbSDimitry Andric void simplifyAffectedPhis(); 2945ffd83dbSDimitry Andric 2950b57cec5SDimitry Andric void killTerminator(BasicBlock *BB); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric void changeExit(RegionNode *Node, BasicBlock *NewExit, 2980b57cec5SDimitry Andric bool IncludeDominator); 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric BasicBlock *getNextFlow(BasicBlock *Dominator); 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric BasicBlock *needPrefix(bool NeedEmpty); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric BasicBlock *needPostfix(BasicBlock *Flow, bool ExitUseAllowed); 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric void setPrevNode(BasicBlock *BB); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric bool dominatesPredicates(BasicBlock *BB, RegionNode *Node); 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric bool isPredictableTrue(RegionNode *Node); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric void wireFlow(bool ExitUseAllowed, BasicBlock *LoopEnd); 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric void handleLoops(bool ExitUseAllowed, BasicBlock *LoopEnd); 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric void createFlow(); 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric void rebuildSSA(); 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric public: 321e8d8bef9SDimitry Andric void init(Region *R); 322e8d8bef9SDimitry Andric bool run(Region *R, DominatorTree *DT); 32306c3fb27SDimitry Andric bool makeUniformRegion(Region *R, UniformityInfo &UA); 324e8d8bef9SDimitry Andric }; 325e8d8bef9SDimitry Andric 326e8d8bef9SDimitry Andric class StructurizeCFGLegacyPass : public RegionPass { 327e8d8bef9SDimitry Andric bool SkipUniformRegions; 328e8d8bef9SDimitry Andric 329e8d8bef9SDimitry Andric public: 3300b57cec5SDimitry Andric static char ID; 3310b57cec5SDimitry Andric 332e8d8bef9SDimitry Andric explicit StructurizeCFGLegacyPass(bool SkipUniformRegions_ = false) 333e8d8bef9SDimitry Andric : RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) { 3340b57cec5SDimitry Andric if (ForceSkipUniformRegions.getNumOccurrences()) 3350b57cec5SDimitry Andric SkipUniformRegions = ForceSkipUniformRegions.getValue(); 336e8d8bef9SDimitry Andric initializeStructurizeCFGLegacyPassPass(*PassRegistry::getPassRegistry()); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 339e8d8bef9SDimitry Andric bool runOnRegion(Region *R, RGPassManager &RGM) override { 340e8d8bef9SDimitry Andric StructurizeCFG SCFG; 341e8d8bef9SDimitry Andric SCFG.init(R); 342e8d8bef9SDimitry Andric if (SkipUniformRegions) { 34306c3fb27SDimitry Andric UniformityInfo &UA = 34406c3fb27SDimitry Andric getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo(); 34506c3fb27SDimitry Andric if (SCFG.makeUniformRegion(R, UA)) 346e8d8bef9SDimitry Andric return false; 347e8d8bef9SDimitry Andric } 348e8d8bef9SDimitry Andric DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 349e8d8bef9SDimitry Andric return SCFG.run(R, DT); 350e8d8bef9SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric StringRef getPassName() const override { return "Structurize control flow"; } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 3550b57cec5SDimitry Andric if (SkipUniformRegions) 35606c3fb27SDimitry Andric AU.addRequired<UniformityInfoWrapperPass>(); 3570b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 3600b57cec5SDimitry Andric RegionPass::getAnalysisUsage(AU); 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric }; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric } // end anonymous namespace 3650b57cec5SDimitry Andric 366e8d8bef9SDimitry Andric char StructurizeCFGLegacyPass::ID = 0; 3670b57cec5SDimitry Andric 368e8d8bef9SDimitry Andric INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg", 369e8d8bef9SDimitry Andric "Structurize the CFG", false, false) 37006c3fb27SDimitry Andric INITIALIZE_PASS_DEPENDENCY(UniformityInfoWrapperPass) 3710b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 3720b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(RegionInfoPass) 373e8d8bef9SDimitry Andric INITIALIZE_PASS_END(StructurizeCFGLegacyPass, "structurizecfg", 374e8d8bef9SDimitry Andric "Structurize the CFG", false, false) 3750b57cec5SDimitry Andric 3765ffd83dbSDimitry Andric /// Build up the general order of nodes, by performing a topological sort of the 3775ffd83dbSDimitry Andric /// parent region's nodes, while ensuring that there is no outer cycle node 3785ffd83dbSDimitry Andric /// between any two inner cycle nodes. 3790b57cec5SDimitry Andric void StructurizeCFG::orderNodes() { 3805ffd83dbSDimitry Andric Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion), 3815ffd83dbSDimitry Andric GraphTraits<Region *>::nodes_end(ParentRegion))); 3825ffd83dbSDimitry Andric if (Order.empty()) 3835ffd83dbSDimitry Andric return; 3840b57cec5SDimitry Andric 3855ffd83dbSDimitry Andric SmallDenseSet<RegionNode *> Nodes; 3865ffd83dbSDimitry Andric auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion); 3870b57cec5SDimitry Andric 3885ffd83dbSDimitry Andric // A list of range indices of SCCs in Order, to be processed. 3895ffd83dbSDimitry Andric SmallVector<std::pair<unsigned, unsigned>, 8> WorkList; 3905ffd83dbSDimitry Andric unsigned I = 0, E = Order.size(); 3915ffd83dbSDimitry Andric while (true) { 3925ffd83dbSDimitry Andric // Run through all the SCCs in the subgraph starting with Entry. 3935ffd83dbSDimitry Andric for (auto SCCI = 3945ffd83dbSDimitry Andric scc_iterator<SubGraphTraits::NodeRef, SubGraphTraits>::begin( 3955ffd83dbSDimitry Andric EntryNode); 3965ffd83dbSDimitry Andric !SCCI.isAtEnd(); ++SCCI) { 3975ffd83dbSDimitry Andric auto &SCC = *SCCI; 3980b57cec5SDimitry Andric 3995ffd83dbSDimitry Andric // An SCC up to the size of 2, can be reduced to an entry (the last node), 4005ffd83dbSDimitry Andric // and a possible additional node. Therefore, it is already in order, and 4015ffd83dbSDimitry Andric // there is no need to add it to the work-list. 4025ffd83dbSDimitry Andric unsigned Size = SCC.size(); 4035ffd83dbSDimitry Andric if (Size > 2) 4045ffd83dbSDimitry Andric WorkList.emplace_back(I, I + Size); 4050b57cec5SDimitry Andric 4065ffd83dbSDimitry Andric // Add the SCC nodes to the Order array. 407bdd1243dSDimitry Andric for (const auto &N : SCC) { 4085ffd83dbSDimitry Andric assert(I < E && "SCC size mismatch!"); 4095ffd83dbSDimitry Andric Order[I++] = N.first; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric } 4125ffd83dbSDimitry Andric assert(I == E && "SCC size mismatch!"); 4135ffd83dbSDimitry Andric 4145ffd83dbSDimitry Andric // If there are no more SCCs to order, then we are done. 4155ffd83dbSDimitry Andric if (WorkList.empty()) 4165ffd83dbSDimitry Andric break; 4175ffd83dbSDimitry Andric 4185ffd83dbSDimitry Andric std::tie(I, E) = WorkList.pop_back_val(); 4195ffd83dbSDimitry Andric 4205ffd83dbSDimitry Andric // Collect the set of nodes in the SCC's subgraph. These are only the 4215ffd83dbSDimitry Andric // possible child nodes; we do not add the entry (last node) otherwise we 4225ffd83dbSDimitry Andric // will have the same exact SCC all over again. 4235ffd83dbSDimitry Andric Nodes.clear(); 4245ffd83dbSDimitry Andric Nodes.insert(Order.begin() + I, Order.begin() + E - 1); 4255ffd83dbSDimitry Andric 4265ffd83dbSDimitry Andric // Update the entry node. 4275ffd83dbSDimitry Andric EntryNode.first = Order[E - 1]; 4285ffd83dbSDimitry Andric EntryNode.second = &Nodes; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric /// Determine the end of the loops 4330b57cec5SDimitry Andric void StructurizeCFG::analyzeLoops(RegionNode *N) { 4340b57cec5SDimitry Andric if (N->isSubRegion()) { 4350b57cec5SDimitry Andric // Test for exit as back edge 4360b57cec5SDimitry Andric BasicBlock *Exit = N->getNodeAs<Region>()->getExit(); 4370b57cec5SDimitry Andric if (Visited.count(Exit)) 4380b57cec5SDimitry Andric Loops[Exit] = N->getEntry(); 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric } else { 4410b57cec5SDimitry Andric // Test for successors as back edge 4420b57cec5SDimitry Andric BasicBlock *BB = N->getNodeAs<BasicBlock>(); 4430b57cec5SDimitry Andric BranchInst *Term = cast<BranchInst>(BB->getTerminator()); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric for (BasicBlock *Succ : Term->successors()) 4460b57cec5SDimitry Andric if (Visited.count(Succ)) 4470b57cec5SDimitry Andric Loops[Succ] = BB; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric /// Build the condition for one edge 4520b57cec5SDimitry Andric Value *StructurizeCFG::buildCondition(BranchInst *Term, unsigned Idx, 4530b57cec5SDimitry Andric bool Invert) { 4540b57cec5SDimitry Andric Value *Cond = Invert ? BoolFalse : BoolTrue; 4550b57cec5SDimitry Andric if (Term->isConditional()) { 4560b57cec5SDimitry Andric Cond = Term->getCondition(); 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric if (Idx != (unsigned)Invert) 4595ffd83dbSDimitry Andric Cond = invertCondition(Cond); 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric return Cond; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric /// Analyze the predecessors of each block and build up predicates 4650b57cec5SDimitry Andric void StructurizeCFG::gatherPredicates(RegionNode *N) { 4660b57cec5SDimitry Andric RegionInfo *RI = ParentRegion->getRegionInfo(); 4670b57cec5SDimitry Andric BasicBlock *BB = N->getEntry(); 4680b57cec5SDimitry Andric BBPredicates &Pred = Predicates[BB]; 4690b57cec5SDimitry Andric BBPredicates &LPred = LoopPreds[BB]; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric for (BasicBlock *P : predecessors(BB)) { 4720b57cec5SDimitry Andric // Ignore it if it's a branch from outside into our region entry 4730b57cec5SDimitry Andric if (!ParentRegion->contains(P)) 4740b57cec5SDimitry Andric continue; 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric Region *R = RI->getRegionFor(P); 4770b57cec5SDimitry Andric if (R == ParentRegion) { 4780b57cec5SDimitry Andric // It's a top level block in our region 4790b57cec5SDimitry Andric BranchInst *Term = cast<BranchInst>(P->getTerminator()); 4800b57cec5SDimitry Andric for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) { 4810b57cec5SDimitry Andric BasicBlock *Succ = Term->getSuccessor(i); 4820b57cec5SDimitry Andric if (Succ != BB) 4830b57cec5SDimitry Andric continue; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric if (Visited.count(P)) { 4860b57cec5SDimitry Andric // Normal forward edge 4870b57cec5SDimitry Andric if (Term->isConditional()) { 4880b57cec5SDimitry Andric // Try to treat it like an ELSE block 4890b57cec5SDimitry Andric BasicBlock *Other = Term->getSuccessor(!i); 4900b57cec5SDimitry Andric if (Visited.count(Other) && !Loops.count(Other) && 4910b57cec5SDimitry Andric !Pred.count(Other) && !Pred.count(P)) { 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric Pred[Other] = BoolFalse; 4940b57cec5SDimitry Andric Pred[P] = BoolTrue; 4950b57cec5SDimitry Andric continue; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric Pred[P] = buildCondition(Term, i, false); 4990b57cec5SDimitry Andric } else { 5000b57cec5SDimitry Andric // Back edge 5010b57cec5SDimitry Andric LPred[P] = buildCondition(Term, i, true); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric } else { 5050b57cec5SDimitry Andric // It's an exit from a sub region 5060b57cec5SDimitry Andric while (R->getParent() != ParentRegion) 5070b57cec5SDimitry Andric R = R->getParent(); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // Edge from inside a subregion to its entry, ignore it 5100b57cec5SDimitry Andric if (*R == *N) 5110b57cec5SDimitry Andric continue; 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric BasicBlock *Entry = R->getEntry(); 5140b57cec5SDimitry Andric if (Visited.count(Entry)) 5150b57cec5SDimitry Andric Pred[Entry] = BoolTrue; 5160b57cec5SDimitry Andric else 5170b57cec5SDimitry Andric LPred[Entry] = BoolFalse; 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric /// Collect various loop and predicate infos 5230b57cec5SDimitry Andric void StructurizeCFG::collectInfos() { 5240b57cec5SDimitry Andric // Reset predicate 5250b57cec5SDimitry Andric Predicates.clear(); 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric // and loop infos 5280b57cec5SDimitry Andric Loops.clear(); 5290b57cec5SDimitry Andric LoopPreds.clear(); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric // Reset the visited nodes 5320b57cec5SDimitry Andric Visited.clear(); 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric for (RegionNode *RN : reverse(Order)) { 5350b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting: " 5360b57cec5SDimitry Andric << (RN->isSubRegion() ? "SubRegion with entry: " : "") 5375ffd83dbSDimitry Andric << RN->getEntry()->getName() << "\n"); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // Analyze all the conditions leading to a node 5400b57cec5SDimitry Andric gatherPredicates(RN); 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric // Remember that we've seen this node 5430b57cec5SDimitry Andric Visited.insert(RN->getEntry()); 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric // Find the last back edges 5460b57cec5SDimitry Andric analyzeLoops(RN); 5470b57cec5SDimitry Andric } 548bdd1243dSDimitry Andric 549bdd1243dSDimitry Andric // Reset the collected term debug locations 550bdd1243dSDimitry Andric TermDL.clear(); 551bdd1243dSDimitry Andric 552bdd1243dSDimitry Andric for (BasicBlock &BB : *Func) { 553bdd1243dSDimitry Andric if (const DebugLoc &DL = BB.getTerminator()->getDebugLoc()) 554bdd1243dSDimitry Andric TermDL[&BB] = DL; 555bdd1243dSDimitry Andric } 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric /// Insert the missing branch conditions 5590b57cec5SDimitry Andric void StructurizeCFG::insertConditions(bool Loops) { 5600b57cec5SDimitry Andric BranchVector &Conds = Loops ? LoopConds : Conditions; 5610b57cec5SDimitry Andric Value *Default = Loops ? BoolTrue : BoolFalse; 5620b57cec5SDimitry Andric SSAUpdater PhiInserter; 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric for (BranchInst *Term : Conds) { 5650b57cec5SDimitry Andric assert(Term->isConditional()); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric BasicBlock *Parent = Term->getParent(); 5680b57cec5SDimitry Andric BasicBlock *SuccTrue = Term->getSuccessor(0); 5690b57cec5SDimitry Andric BasicBlock *SuccFalse = Term->getSuccessor(1); 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric PhiInserter.Initialize(Boolean, ""); 5720b57cec5SDimitry Andric PhiInserter.AddAvailableValue(&Func->getEntryBlock(), Default); 5730b57cec5SDimitry Andric PhiInserter.AddAvailableValue(Loops ? SuccFalse : Parent, Default); 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue]; 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric NearestCommonDominator Dominator(DT); 5780b57cec5SDimitry Andric Dominator.addBlock(Parent); 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric Value *ParentValue = nullptr; 5810b57cec5SDimitry Andric for (std::pair<BasicBlock *, Value *> BBAndPred : Preds) { 5820b57cec5SDimitry Andric BasicBlock *BB = BBAndPred.first; 5830b57cec5SDimitry Andric Value *Pred = BBAndPred.second; 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric if (BB == Parent) { 5860b57cec5SDimitry Andric ParentValue = Pred; 5870b57cec5SDimitry Andric break; 5880b57cec5SDimitry Andric } 5890b57cec5SDimitry Andric PhiInserter.AddAvailableValue(BB, Pred); 5900b57cec5SDimitry Andric Dominator.addAndRememberBlock(BB); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric if (ParentValue) { 5940b57cec5SDimitry Andric Term->setCondition(ParentValue); 5950b57cec5SDimitry Andric } else { 5960b57cec5SDimitry Andric if (!Dominator.resultIsRememberedBlock()) 5970b57cec5SDimitry Andric PhiInserter.AddAvailableValue(Dominator.result(), Default); 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric Term->setCondition(PhiInserter.GetValueInMiddleOfBlock(Parent)); 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6041fd87a68SDimitry Andric /// Simplify any inverted conditions that were built by buildConditions. 6051fd87a68SDimitry Andric void StructurizeCFG::simplifyConditions() { 6061fd87a68SDimitry Andric SmallVector<Instruction *> InstToErase; 6071fd87a68SDimitry Andric for (auto &I : concat<PredMap::value_type>(Predicates, LoopPreds)) { 6081fd87a68SDimitry Andric auto &Preds = I.second; 6091fd87a68SDimitry Andric for (auto &J : Preds) { 6101fd87a68SDimitry Andric auto &Cond = J.second; 6111fd87a68SDimitry Andric Instruction *Inverted; 6121fd87a68SDimitry Andric if (match(Cond, m_Not(m_OneUse(m_Instruction(Inverted)))) && 6131fd87a68SDimitry Andric !Cond->use_empty()) { 6141fd87a68SDimitry Andric if (auto *InvertedCmp = dyn_cast<CmpInst>(Inverted)) { 6151fd87a68SDimitry Andric InvertedCmp->setPredicate(InvertedCmp->getInversePredicate()); 6161fd87a68SDimitry Andric Cond->replaceAllUsesWith(InvertedCmp); 6171fd87a68SDimitry Andric InstToErase.push_back(cast<Instruction>(Cond)); 6181fd87a68SDimitry Andric } 6191fd87a68SDimitry Andric } 6201fd87a68SDimitry Andric } 6211fd87a68SDimitry Andric } 6221fd87a68SDimitry Andric for (auto *I : InstToErase) 6231fd87a68SDimitry Andric I->eraseFromParent(); 6241fd87a68SDimitry Andric } 6251fd87a68SDimitry Andric 6260b57cec5SDimitry Andric /// Remove all PHI values coming from "From" into "To" and remember 6270b57cec5SDimitry Andric /// them in DeletedPhis 6280b57cec5SDimitry Andric void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) { 6290b57cec5SDimitry Andric PhiMap &Map = DeletedPhis[To]; 6300b57cec5SDimitry Andric for (PHINode &Phi : To->phis()) { 6315ffd83dbSDimitry Andric bool Recorded = false; 6320b57cec5SDimitry Andric while (Phi.getBasicBlockIndex(From) != -1) { 6330b57cec5SDimitry Andric Value *Deleted = Phi.removeIncomingValue(From, false); 6340b57cec5SDimitry Andric Map[&Phi].push_back(std::make_pair(From, Deleted)); 6355ffd83dbSDimitry Andric if (!Recorded) { 6365ffd83dbSDimitry Andric AffectedPhis.push_back(&Phi); 6375ffd83dbSDimitry Andric Recorded = true; 6385ffd83dbSDimitry Andric } 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric /// Add a dummy PHI value as soon as we knew the new predecessor 6440b57cec5SDimitry Andric void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) { 6450b57cec5SDimitry Andric for (PHINode &Phi : To->phis()) { 6460b57cec5SDimitry Andric Value *Undef = UndefValue::get(Phi.getType()); 6470b57cec5SDimitry Andric Phi.addIncoming(Undef, From); 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric AddedPhis[To].push_back(From); 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 652bdd1243dSDimitry Andric /// When we are reconstructing a PHI inside \p PHIBlock with incoming values 653bdd1243dSDimitry Andric /// from predecessors \p Incomings, we have a chance to mark the available value 654bdd1243dSDimitry Andric /// from some blocks as undefined. The function will find out all such blocks 655bdd1243dSDimitry Andric /// and return in \p UndefBlks. 656bdd1243dSDimitry Andric void StructurizeCFG::findUndefBlocks( 657bdd1243dSDimitry Andric BasicBlock *PHIBlock, const SmallSet<BasicBlock *, 8> &Incomings, 658bdd1243dSDimitry Andric SmallVector<BasicBlock *> &UndefBlks) const { 659bdd1243dSDimitry Andric // We may get a post-structured CFG like below: 660bdd1243dSDimitry Andric // 661bdd1243dSDimitry Andric // | P1 662bdd1243dSDimitry Andric // |/ 663bdd1243dSDimitry Andric // F1 664bdd1243dSDimitry Andric // |\ 665bdd1243dSDimitry Andric // | N 666bdd1243dSDimitry Andric // |/ 667bdd1243dSDimitry Andric // F2 668bdd1243dSDimitry Andric // |\ 669bdd1243dSDimitry Andric // | P2 670bdd1243dSDimitry Andric // |/ 671bdd1243dSDimitry Andric // F3 672bdd1243dSDimitry Andric // |\ 673bdd1243dSDimitry Andric // B 674bdd1243dSDimitry Andric // 675bdd1243dSDimitry Andric // B is the block that has a PHI being reconstructed. P1/P2 are predecessors 676bdd1243dSDimitry Andric // of B before structurization. F1/F2/F3 are flow blocks inserted during 677bdd1243dSDimitry Andric // structurization process. Block N is not a predecessor of B before 678bdd1243dSDimitry Andric // structurization, but are placed between the predecessors(P1/P2) of B after 679bdd1243dSDimitry Andric // structurization. This usually means that threads went to N never take the 680bdd1243dSDimitry Andric // path N->F2->F3->B. For example, the threads take the branch F1->N may 681bdd1243dSDimitry Andric // always take the branch F2->P2. So, when we are reconstructing a PHI 682bdd1243dSDimitry Andric // originally in B, we can safely say the incoming value from N is undefined. 683bdd1243dSDimitry Andric SmallSet<BasicBlock *, 8> VisitedBlock; 684bdd1243dSDimitry Andric SmallVector<BasicBlock *, 8> Stack; 685bdd1243dSDimitry Andric if (PHIBlock == ParentRegion->getExit()) { 686bdd1243dSDimitry Andric for (auto P : predecessors(PHIBlock)) { 687bdd1243dSDimitry Andric if (ParentRegion->contains(P)) 688bdd1243dSDimitry Andric Stack.push_back(P); 689bdd1243dSDimitry Andric } 690bdd1243dSDimitry Andric } else { 691bdd1243dSDimitry Andric append_range(Stack, predecessors(PHIBlock)); 692bdd1243dSDimitry Andric } 693bdd1243dSDimitry Andric 694bdd1243dSDimitry Andric // Do a backward traversal over the CFG, and stop further searching if 695bdd1243dSDimitry Andric // the block is not a Flow. If a block is neither flow block nor the 696bdd1243dSDimitry Andric // incoming predecessor, then the incoming value from the block is 697bdd1243dSDimitry Andric // undefined value for the PHI being reconstructed. 698bdd1243dSDimitry Andric while (!Stack.empty()) { 699bdd1243dSDimitry Andric BasicBlock *Current = Stack.pop_back_val(); 700bdd1243dSDimitry Andric if (VisitedBlock.contains(Current)) 701bdd1243dSDimitry Andric continue; 702bdd1243dSDimitry Andric 703bdd1243dSDimitry Andric VisitedBlock.insert(Current); 704bdd1243dSDimitry Andric if (FlowSet.contains(Current)) { 705bdd1243dSDimitry Andric for (auto P : predecessors(Current)) 706bdd1243dSDimitry Andric Stack.push_back(P); 707bdd1243dSDimitry Andric } else if (!Incomings.contains(Current)) { 708bdd1243dSDimitry Andric UndefBlks.push_back(Current); 709bdd1243dSDimitry Andric } 710bdd1243dSDimitry Andric } 711bdd1243dSDimitry Andric } 712bdd1243dSDimitry Andric 7130b57cec5SDimitry Andric /// Add the real PHI value as soon as everything is set up 7140b57cec5SDimitry Andric void StructurizeCFG::setPhiValues() { 7150b57cec5SDimitry Andric SmallVector<PHINode *, 8> InsertedPhis; 7160b57cec5SDimitry Andric SSAUpdater Updater(&InsertedPhis); 7170b57cec5SDimitry Andric for (const auto &AddedPhi : AddedPhis) { 7180b57cec5SDimitry Andric BasicBlock *To = AddedPhi.first; 7190b57cec5SDimitry Andric const BBVector &From = AddedPhi.second; 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric if (!DeletedPhis.count(To)) 7220b57cec5SDimitry Andric continue; 7230b57cec5SDimitry Andric 724bdd1243dSDimitry Andric SmallVector<BasicBlock *> UndefBlks; 725bdd1243dSDimitry Andric bool CachedUndefs = false; 7260b57cec5SDimitry Andric PhiMap &Map = DeletedPhis[To]; 7270b57cec5SDimitry Andric for (const auto &PI : Map) { 7280b57cec5SDimitry Andric PHINode *Phi = PI.first; 7290b57cec5SDimitry Andric Value *Undef = UndefValue::get(Phi->getType()); 7300b57cec5SDimitry Andric Updater.Initialize(Phi->getType(), ""); 7310b57cec5SDimitry Andric Updater.AddAvailableValue(&Func->getEntryBlock(), Undef); 7320b57cec5SDimitry Andric Updater.AddAvailableValue(To, Undef); 7330b57cec5SDimitry Andric 734bdd1243dSDimitry Andric SmallSet<BasicBlock *, 8> Incomings; 735bdd1243dSDimitry Andric SmallVector<BasicBlock *> ConstantPreds; 7360b57cec5SDimitry Andric for (const auto &VI : PI.second) { 737bdd1243dSDimitry Andric Incomings.insert(VI.first); 7380b57cec5SDimitry Andric Updater.AddAvailableValue(VI.first, VI.second); 739bdd1243dSDimitry Andric if (isa<Constant>(VI.second)) 740bdd1243dSDimitry Andric ConstantPreds.push_back(VI.first); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 743bdd1243dSDimitry Andric if (!CachedUndefs) { 744bdd1243dSDimitry Andric findUndefBlocks(To, Incomings, UndefBlks); 745bdd1243dSDimitry Andric CachedUndefs = true; 746bdd1243dSDimitry Andric } 747bdd1243dSDimitry Andric 748bdd1243dSDimitry Andric for (auto UB : UndefBlks) { 749bdd1243dSDimitry Andric // If this undef block is dominated by any predecessor(before 750bdd1243dSDimitry Andric // structurization) of reconstructed PHI with constant incoming value, 751bdd1243dSDimitry Andric // don't mark the available value as undefined. Setting undef to such 752bdd1243dSDimitry Andric // block will stop us from getting optimal phi insertion. 753bdd1243dSDimitry Andric if (any_of(ConstantPreds, 754bdd1243dSDimitry Andric [&](BasicBlock *CP) { return DT->dominates(CP, UB); })) 755bdd1243dSDimitry Andric continue; 756bdd1243dSDimitry Andric Updater.AddAvailableValue(UB, Undef); 757bdd1243dSDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric for (BasicBlock *FI : From) 7600b57cec5SDimitry Andric Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI)); 7615ffd83dbSDimitry Andric AffectedPhis.push_back(Phi); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric DeletedPhis.erase(To); 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric assert(DeletedPhis.empty()); 7670b57cec5SDimitry Andric 7685ffd83dbSDimitry Andric AffectedPhis.append(InsertedPhis.begin(), InsertedPhis.end()); 7695ffd83dbSDimitry Andric } 7705ffd83dbSDimitry Andric 7715ffd83dbSDimitry Andric void StructurizeCFG::simplifyAffectedPhis() { 7720b57cec5SDimitry Andric bool Changed; 7730b57cec5SDimitry Andric do { 7740b57cec5SDimitry Andric Changed = false; 775*0fca6ea1SDimitry Andric SimplifyQuery Q(Func->getDataLayout()); 7760b57cec5SDimitry Andric Q.DT = DT; 777bdd1243dSDimitry Andric // Setting CanUseUndef to true might extend value liveness, set it to false 778bdd1243dSDimitry Andric // to achieve better register pressure. 779bdd1243dSDimitry Andric Q.CanUseUndef = false; 7805ffd83dbSDimitry Andric for (WeakVH VH : AffectedPhis) { 7815ffd83dbSDimitry Andric if (auto Phi = dyn_cast_or_null<PHINode>(VH)) { 78281ad6265SDimitry Andric if (auto NewValue = simplifyInstruction(Phi, Q)) { 7835ffd83dbSDimitry Andric Phi->replaceAllUsesWith(NewValue); 7840b57cec5SDimitry Andric Phi->eraseFromParent(); 7850b57cec5SDimitry Andric Changed = true; 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric } 7885ffd83dbSDimitry Andric } 7890b57cec5SDimitry Andric } while (Changed); 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric /// Remove phi values from all successors and then remove the terminator. 7930b57cec5SDimitry Andric void StructurizeCFG::killTerminator(BasicBlock *BB) { 7940b57cec5SDimitry Andric Instruction *Term = BB->getTerminator(); 7950b57cec5SDimitry Andric if (!Term) 7960b57cec5SDimitry Andric return; 7970b57cec5SDimitry Andric 798fe6060f1SDimitry Andric for (BasicBlock *Succ : successors(BB)) 799fe6060f1SDimitry Andric delPhiValues(BB, Succ); 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric Term->eraseFromParent(); 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric /// Let node exit(s) point to NewExit 8050b57cec5SDimitry Andric void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit, 8060b57cec5SDimitry Andric bool IncludeDominator) { 8070b57cec5SDimitry Andric if (Node->isSubRegion()) { 8080b57cec5SDimitry Andric Region *SubRegion = Node->getNodeAs<Region>(); 8090b57cec5SDimitry Andric BasicBlock *OldExit = SubRegion->getExit(); 8100b57cec5SDimitry Andric BasicBlock *Dominator = nullptr; 8110b57cec5SDimitry Andric 812fe6060f1SDimitry Andric // Find all the edges from the sub region to the exit. 813fe6060f1SDimitry Andric // We use make_early_inc_range here because we modify BB's terminator. 814fe6060f1SDimitry Andric for (BasicBlock *BB : llvm::make_early_inc_range(predecessors(OldExit))) { 8150b57cec5SDimitry Andric if (!SubRegion->contains(BB)) 8160b57cec5SDimitry Andric continue; 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric // Modify the edges to point to the new exit 8190b57cec5SDimitry Andric delPhiValues(BB, OldExit); 8200b57cec5SDimitry Andric BB->getTerminator()->replaceUsesOfWith(OldExit, NewExit); 8210b57cec5SDimitry Andric addPhiValues(BB, NewExit); 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric // Find the new dominator (if requested) 8240b57cec5SDimitry Andric if (IncludeDominator) { 8250b57cec5SDimitry Andric if (!Dominator) 8260b57cec5SDimitry Andric Dominator = BB; 8270b57cec5SDimitry Andric else 8280b57cec5SDimitry Andric Dominator = DT->findNearestCommonDominator(Dominator, BB); 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // Change the dominator (if requested) 8330b57cec5SDimitry Andric if (Dominator) 8340b57cec5SDimitry Andric DT->changeImmediateDominator(NewExit, Dominator); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // Update the region info 8370b57cec5SDimitry Andric SubRegion->replaceExit(NewExit); 8380b57cec5SDimitry Andric } else { 8390b57cec5SDimitry Andric BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 8400b57cec5SDimitry Andric killTerminator(BB); 841bdd1243dSDimitry Andric BranchInst *Br = BranchInst::Create(NewExit, BB); 842bdd1243dSDimitry Andric Br->setDebugLoc(TermDL[BB]); 8430b57cec5SDimitry Andric addPhiValues(BB, NewExit); 8440b57cec5SDimitry Andric if (IncludeDominator) 8450b57cec5SDimitry Andric DT->changeImmediateDominator(NewExit, BB); 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric /// Create a new flow node and update dominator tree and region info 8500b57cec5SDimitry Andric BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) { 8510b57cec5SDimitry Andric LLVMContext &Context = Func->getContext(); 8520b57cec5SDimitry Andric BasicBlock *Insert = Order.empty() ? ParentRegion->getExit() : 8530b57cec5SDimitry Andric Order.back()->getEntry(); 8540b57cec5SDimitry Andric BasicBlock *Flow = BasicBlock::Create(Context, FlowBlockName, 8550b57cec5SDimitry Andric Func, Insert); 856bdd1243dSDimitry Andric FlowSet.insert(Flow); 857bdd1243dSDimitry Andric 858bdd1243dSDimitry Andric // use a temporary variable to avoid a use-after-free if the map's storage is 859bdd1243dSDimitry Andric // reallocated 860bdd1243dSDimitry Andric DebugLoc DL = TermDL[Dominator]; 861bdd1243dSDimitry Andric TermDL[Flow] = std::move(DL); 862bdd1243dSDimitry Andric 8630b57cec5SDimitry Andric DT->addNewBlock(Flow, Dominator); 8640b57cec5SDimitry Andric ParentRegion->getRegionInfo()->setRegionFor(Flow, ParentRegion); 8650b57cec5SDimitry Andric return Flow; 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric /// Create a new or reuse the previous node as flow node 8690b57cec5SDimitry Andric BasicBlock *StructurizeCFG::needPrefix(bool NeedEmpty) { 8700b57cec5SDimitry Andric BasicBlock *Entry = PrevNode->getEntry(); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric if (!PrevNode->isSubRegion()) { 8730b57cec5SDimitry Andric killTerminator(Entry); 8740b57cec5SDimitry Andric if (!NeedEmpty || Entry->getFirstInsertionPt() == Entry->end()) 8750b57cec5SDimitry Andric return Entry; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric // create a new flow node 8790b57cec5SDimitry Andric BasicBlock *Flow = getNextFlow(Entry); 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric // and wire it up 8820b57cec5SDimitry Andric changeExit(PrevNode, Flow, true); 8830b57cec5SDimitry Andric PrevNode = ParentRegion->getBBNode(Flow); 8840b57cec5SDimitry Andric return Flow; 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric /// Returns the region exit if possible, otherwise just a new flow node 8880b57cec5SDimitry Andric BasicBlock *StructurizeCFG::needPostfix(BasicBlock *Flow, 8890b57cec5SDimitry Andric bool ExitUseAllowed) { 8900b57cec5SDimitry Andric if (!Order.empty() || !ExitUseAllowed) 8910b57cec5SDimitry Andric return getNextFlow(Flow); 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric BasicBlock *Exit = ParentRegion->getExit(); 8940b57cec5SDimitry Andric DT->changeImmediateDominator(Exit, Flow); 8950b57cec5SDimitry Andric addPhiValues(Flow, Exit); 8960b57cec5SDimitry Andric return Exit; 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric /// Set the previous node 9000b57cec5SDimitry Andric void StructurizeCFG::setPrevNode(BasicBlock *BB) { 9010b57cec5SDimitry Andric PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB) 9020b57cec5SDimitry Andric : nullptr; 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric /// Does BB dominate all the predicates of Node? 9060b57cec5SDimitry Andric bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) { 9070b57cec5SDimitry Andric BBPredicates &Preds = Predicates[Node->getEntry()]; 9080b57cec5SDimitry Andric return llvm::all_of(Preds, [&](std::pair<BasicBlock *, Value *> Pred) { 9090b57cec5SDimitry Andric return DT->dominates(BB, Pred.first); 9100b57cec5SDimitry Andric }); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric /// Can we predict that this node will always be called? 9140b57cec5SDimitry Andric bool StructurizeCFG::isPredictableTrue(RegionNode *Node) { 9150b57cec5SDimitry Andric BBPredicates &Preds = Predicates[Node->getEntry()]; 9160b57cec5SDimitry Andric bool Dominated = false; 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric // Regionentry is always true 9190b57cec5SDimitry Andric if (!PrevNode) 9200b57cec5SDimitry Andric return true; 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric for (std::pair<BasicBlock*, Value*> Pred : Preds) { 9230b57cec5SDimitry Andric BasicBlock *BB = Pred.first; 9240b57cec5SDimitry Andric Value *V = Pred.second; 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric if (V != BoolTrue) 9270b57cec5SDimitry Andric return false; 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric if (!Dominated && DT->dominates(BB, PrevNode->getEntry())) 9300b57cec5SDimitry Andric Dominated = true; 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric // TODO: The dominator check is too strict 9340b57cec5SDimitry Andric return Dominated; 9350b57cec5SDimitry Andric } 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric /// Take one node from the order vector and wire it up 9380b57cec5SDimitry Andric void StructurizeCFG::wireFlow(bool ExitUseAllowed, 9390b57cec5SDimitry Andric BasicBlock *LoopEnd) { 9400b57cec5SDimitry Andric RegionNode *Node = Order.pop_back_val(); 9410b57cec5SDimitry Andric Visited.insert(Node->getEntry()); 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric if (isPredictableTrue(Node)) { 9440b57cec5SDimitry Andric // Just a linear flow 9450b57cec5SDimitry Andric if (PrevNode) { 9460b57cec5SDimitry Andric changeExit(PrevNode, Node->getEntry(), true); 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric PrevNode = Node; 9490b57cec5SDimitry Andric } else { 9500b57cec5SDimitry Andric // Insert extra prefix node (or reuse last one) 9510b57cec5SDimitry Andric BasicBlock *Flow = needPrefix(false); 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric // Insert extra postfix node (or use exit instead) 9540b57cec5SDimitry Andric BasicBlock *Entry = Node->getEntry(); 9550b57cec5SDimitry Andric BasicBlock *Next = needPostfix(Flow, ExitUseAllowed); 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric // let it point to entry and next block 95806c3fb27SDimitry Andric BranchInst *Br = BranchInst::Create(Entry, Next, BoolPoison, Flow); 959bdd1243dSDimitry Andric Br->setDebugLoc(TermDL[Flow]); 960bdd1243dSDimitry Andric Conditions.push_back(Br); 9610b57cec5SDimitry Andric addPhiValues(Flow, Entry); 9620b57cec5SDimitry Andric DT->changeImmediateDominator(Entry, Flow); 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric PrevNode = Node; 9650b57cec5SDimitry Andric while (!Order.empty() && !Visited.count(LoopEnd) && 9660b57cec5SDimitry Andric dominatesPredicates(Entry, Order.back())) { 9670b57cec5SDimitry Andric handleLoops(false, LoopEnd); 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric changeExit(PrevNode, Next, false); 9710b57cec5SDimitry Andric setPrevNode(Next); 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric void StructurizeCFG::handleLoops(bool ExitUseAllowed, 9760b57cec5SDimitry Andric BasicBlock *LoopEnd) { 9770b57cec5SDimitry Andric RegionNode *Node = Order.back(); 9780b57cec5SDimitry Andric BasicBlock *LoopStart = Node->getEntry(); 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric if (!Loops.count(LoopStart)) { 9810b57cec5SDimitry Andric wireFlow(ExitUseAllowed, LoopEnd); 9820b57cec5SDimitry Andric return; 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric if (!isPredictableTrue(Node)) 9860b57cec5SDimitry Andric LoopStart = needPrefix(true); 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric LoopEnd = Loops[Node->getEntry()]; 9890b57cec5SDimitry Andric wireFlow(false, LoopEnd); 9900b57cec5SDimitry Andric while (!Visited.count(LoopEnd)) { 9910b57cec5SDimitry Andric handleLoops(false, LoopEnd); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 994bdd1243dSDimitry Andric assert(LoopStart != &LoopStart->getParent()->getEntryBlock()); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // Create an extra loop end node 9970b57cec5SDimitry Andric LoopEnd = needPrefix(false); 9980b57cec5SDimitry Andric BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed); 99906c3fb27SDimitry Andric BranchInst *Br = BranchInst::Create(Next, LoopStart, BoolPoison, LoopEnd); 1000bdd1243dSDimitry Andric Br->setDebugLoc(TermDL[LoopEnd]); 1001bdd1243dSDimitry Andric LoopConds.push_back(Br); 10020b57cec5SDimitry Andric addPhiValues(LoopEnd, LoopStart); 10030b57cec5SDimitry Andric setPrevNode(Next); 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric /// After this function control flow looks like it should be, but 10070b57cec5SDimitry Andric /// branches and PHI nodes only have undefined conditions. 10080b57cec5SDimitry Andric void StructurizeCFG::createFlow() { 10090b57cec5SDimitry Andric BasicBlock *Exit = ParentRegion->getExit(); 10100b57cec5SDimitry Andric bool EntryDominatesExit = DT->dominates(ParentRegion->getEntry(), Exit); 10110b57cec5SDimitry Andric 10125ffd83dbSDimitry Andric AffectedPhis.clear(); 10130b57cec5SDimitry Andric DeletedPhis.clear(); 10140b57cec5SDimitry Andric AddedPhis.clear(); 10150b57cec5SDimitry Andric Conditions.clear(); 10160b57cec5SDimitry Andric LoopConds.clear(); 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric PrevNode = nullptr; 10190b57cec5SDimitry Andric Visited.clear(); 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric while (!Order.empty()) { 10220b57cec5SDimitry Andric handleLoops(EntryDominatesExit, nullptr); 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric if (PrevNode) 10260b57cec5SDimitry Andric changeExit(PrevNode, Exit, EntryDominatesExit); 10270b57cec5SDimitry Andric else 10280b57cec5SDimitry Andric assert(EntryDominatesExit); 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric /// Handle a rare case where the disintegrated nodes instructions 10320b57cec5SDimitry Andric /// no longer dominate all their uses. Not sure if this is really necessary 10330b57cec5SDimitry Andric void StructurizeCFG::rebuildSSA() { 10340b57cec5SDimitry Andric SSAUpdater Updater; 10350b57cec5SDimitry Andric for (BasicBlock *BB : ParentRegion->blocks()) 10360b57cec5SDimitry Andric for (Instruction &I : *BB) { 10370b57cec5SDimitry Andric bool Initialized = false; 1038fe6060f1SDimitry Andric // We may modify the use list as we iterate over it, so we use 1039fe6060f1SDimitry Andric // make_early_inc_range. 1040fe6060f1SDimitry Andric for (Use &U : llvm::make_early_inc_range(I.uses())) { 10410b57cec5SDimitry Andric Instruction *User = cast<Instruction>(U.getUser()); 10420b57cec5SDimitry Andric if (User->getParent() == BB) { 10430b57cec5SDimitry Andric continue; 10440b57cec5SDimitry Andric } else if (PHINode *UserPN = dyn_cast<PHINode>(User)) { 10450b57cec5SDimitry Andric if (UserPN->getIncomingBlock(U) == BB) 10460b57cec5SDimitry Andric continue; 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric if (DT->dominates(&I, User)) 10500b57cec5SDimitry Andric continue; 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric if (!Initialized) { 10530b57cec5SDimitry Andric Value *Undef = UndefValue::get(I.getType()); 10540b57cec5SDimitry Andric Updater.Initialize(I.getType(), ""); 10550b57cec5SDimitry Andric Updater.AddAvailableValue(&Func->getEntryBlock(), Undef); 10560b57cec5SDimitry Andric Updater.AddAvailableValue(BB, &I); 10570b57cec5SDimitry Andric Initialized = true; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric Updater.RewriteUseAfterInsertions(U); 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, 106506c3fb27SDimitry Andric const UniformityInfo &UA) { 10660b57cec5SDimitry Andric // Bool for if all sub-regions are uniform. 10670b57cec5SDimitry Andric bool SubRegionsAreUniform = true; 10680b57cec5SDimitry Andric // Count of how many direct children are conditional. 10690b57cec5SDimitry Andric unsigned ConditionalDirectChildren = 0; 10700b57cec5SDimitry Andric 1071bdd1243dSDimitry Andric for (auto *E : R->elements()) { 10720b57cec5SDimitry Andric if (!E->isSubRegion()) { 10730b57cec5SDimitry Andric auto Br = dyn_cast<BranchInst>(E->getEntry()->getTerminator()); 10740b57cec5SDimitry Andric if (!Br || !Br->isConditional()) 10750b57cec5SDimitry Andric continue; 10760b57cec5SDimitry Andric 107706c3fb27SDimitry Andric if (!UA.isUniform(Br)) 10780b57cec5SDimitry Andric return false; 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric // One of our direct children is conditional. 10810b57cec5SDimitry Andric ConditionalDirectChildren++; 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "BB: " << Br->getParent()->getName() 10840b57cec5SDimitry Andric << " has uniform terminator\n"); 10850b57cec5SDimitry Andric } else { 10860b57cec5SDimitry Andric // Explicitly refuse to treat regions as uniform if they have non-uniform 108706c3fb27SDimitry Andric // subregions. We cannot rely on UniformityAnalysis for branches in 10880b57cec5SDimitry Andric // subregions because those branches may have been removed and re-created, 10890b57cec5SDimitry Andric // so we look for our metadata instead. 10900b57cec5SDimitry Andric // 10910b57cec5SDimitry Andric // Warning: It would be nice to treat regions as uniform based only on 10920b57cec5SDimitry Andric // their direct child basic blocks' terminators, regardless of whether 10930b57cec5SDimitry Andric // subregions are uniform or not. However, this requires a very careful 10940b57cec5SDimitry Andric // look at SIAnnotateControlFlow to make sure nothing breaks there. 1095bdd1243dSDimitry Andric for (auto *BB : E->getNodeAs<Region>()->blocks()) { 10960b57cec5SDimitry Andric auto Br = dyn_cast<BranchInst>(BB->getTerminator()); 10970b57cec5SDimitry Andric if (!Br || !Br->isConditional()) 10980b57cec5SDimitry Andric continue; 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric if (!Br->getMetadata(UniformMDKindID)) { 11010b57cec5SDimitry Andric // Early exit if we cannot have relaxed uniform regions. 11020b57cec5SDimitry Andric if (!RelaxedUniformRegions) 11030b57cec5SDimitry Andric return false; 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric SubRegionsAreUniform = false; 11060b57cec5SDimitry Andric break; 11070b57cec5SDimitry Andric } 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric // Our region is uniform if: 11130b57cec5SDimitry Andric // 1. All conditional branches that are direct children are uniform (checked 11140b57cec5SDimitry Andric // above). 11150b57cec5SDimitry Andric // 2. And either: 11160b57cec5SDimitry Andric // a. All sub-regions are uniform. 11170b57cec5SDimitry Andric // b. There is one or less conditional branches among the direct children. 11180b57cec5SDimitry Andric return SubRegionsAreUniform || (ConditionalDirectChildren <= 1); 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric 1121e8d8bef9SDimitry Andric void StructurizeCFG::init(Region *R) { 1122e8d8bef9SDimitry Andric LLVMContext &Context = R->getEntry()->getContext(); 1123e8d8bef9SDimitry Andric 1124e8d8bef9SDimitry Andric Boolean = Type::getInt1Ty(Context); 1125e8d8bef9SDimitry Andric BoolTrue = ConstantInt::getTrue(Context); 1126e8d8bef9SDimitry Andric BoolFalse = ConstantInt::getFalse(Context); 112706c3fb27SDimitry Andric BoolPoison = PoisonValue::get(Boolean); 1128e8d8bef9SDimitry Andric 112906c3fb27SDimitry Andric this->UA = nullptr; 1130e8d8bef9SDimitry Andric } 1131e8d8bef9SDimitry Andric 113206c3fb27SDimitry Andric bool StructurizeCFG::makeUniformRegion(Region *R, UniformityInfo &UA) { 11330b57cec5SDimitry Andric if (R->isTopLevelRegion()) 11340b57cec5SDimitry Andric return false; 11350b57cec5SDimitry Andric 113606c3fb27SDimitry Andric this->UA = &UA; 113706c3fb27SDimitry Andric 11380b57cec5SDimitry Andric // TODO: We could probably be smarter here with how we handle sub-regions. 11390b57cec5SDimitry Andric // We currently rely on the fact that metadata is set by earlier invocations 11400b57cec5SDimitry Andric // of the pass on sub-regions, and that this metadata doesn't get lost -- 11410b57cec5SDimitry Andric // but we shouldn't rely on metadata for correctness! 11420b57cec5SDimitry Andric unsigned UniformMDKindID = 11430b57cec5SDimitry Andric R->getEntry()->getContext().getMDKindID("structurizecfg.uniform"); 11440b57cec5SDimitry Andric 114506c3fb27SDimitry Andric if (hasOnlyUniformBranches(R, UniformMDKindID, UA)) { 11460b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R 11470b57cec5SDimitry Andric << '\n'); 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andric // Mark all direct child block terminators as having been treated as 11500b57cec5SDimitry Andric // uniform. To account for a possible future in which non-uniform 11510b57cec5SDimitry Andric // sub-regions are treated more cleverly, indirect children are not 11520b57cec5SDimitry Andric // marked as uniform. 11530b57cec5SDimitry Andric MDNode *MD = MDNode::get(R->getEntry()->getParent()->getContext(), {}); 11540b57cec5SDimitry Andric for (RegionNode *E : R->elements()) { 11550b57cec5SDimitry Andric if (E->isSubRegion()) 11560b57cec5SDimitry Andric continue; 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric if (Instruction *Term = E->getEntry()->getTerminator()) 11590b57cec5SDimitry Andric Term->setMetadata(UniformMDKindID, MD); 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric 1162e8d8bef9SDimitry Andric return true; 1163e8d8bef9SDimitry Andric } 11640b57cec5SDimitry Andric return false; 11650b57cec5SDimitry Andric } 1166e8d8bef9SDimitry Andric 1167e8d8bef9SDimitry Andric /// Run the transformation for each region found 1168e8d8bef9SDimitry Andric bool StructurizeCFG::run(Region *R, DominatorTree *DT) { 1169e8d8bef9SDimitry Andric if (R->isTopLevelRegion()) 1170e8d8bef9SDimitry Andric return false; 1171e8d8bef9SDimitry Andric 1172e8d8bef9SDimitry Andric this->DT = DT; 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric Func = R->getEntry()->getParent(); 11755f757f3fSDimitry Andric assert(hasOnlySimpleTerminator(*Func) && "Unsupported block terminator."); 11765f757f3fSDimitry Andric 11770b57cec5SDimitry Andric ParentRegion = R; 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric orderNodes(); 11800b57cec5SDimitry Andric collectInfos(); 11810b57cec5SDimitry Andric createFlow(); 11820b57cec5SDimitry Andric insertConditions(false); 11830b57cec5SDimitry Andric insertConditions(true); 11840b57cec5SDimitry Andric setPhiValues(); 118581ad6265SDimitry Andric simplifyConditions(); 11865ffd83dbSDimitry Andric simplifyAffectedPhis(); 11870b57cec5SDimitry Andric rebuildSSA(); 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric // Cleanup 11900b57cec5SDimitry Andric Order.clear(); 11910b57cec5SDimitry Andric Visited.clear(); 11920b57cec5SDimitry Andric DeletedPhis.clear(); 11930b57cec5SDimitry Andric AddedPhis.clear(); 11940b57cec5SDimitry Andric Predicates.clear(); 11950b57cec5SDimitry Andric Conditions.clear(); 11960b57cec5SDimitry Andric Loops.clear(); 11970b57cec5SDimitry Andric LoopPreds.clear(); 11980b57cec5SDimitry Andric LoopConds.clear(); 1199bdd1243dSDimitry Andric FlowSet.clear(); 1200bdd1243dSDimitry Andric TermDL.clear(); 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric return true; 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) { 1206e8d8bef9SDimitry Andric return new StructurizeCFGLegacyPass(SkipUniformRegions); 1207e8d8bef9SDimitry Andric } 1208e8d8bef9SDimitry Andric 1209e8d8bef9SDimitry Andric static void addRegionIntoQueue(Region &R, std::vector<Region *> &Regions) { 1210e8d8bef9SDimitry Andric Regions.push_back(&R); 1211e8d8bef9SDimitry Andric for (const auto &E : R) 1212e8d8bef9SDimitry Andric addRegionIntoQueue(*E, Regions); 1213e8d8bef9SDimitry Andric } 1214e8d8bef9SDimitry Andric 1215e8d8bef9SDimitry Andric PreservedAnalyses StructurizeCFGPass::run(Function &F, 1216e8d8bef9SDimitry Andric FunctionAnalysisManager &AM) { 1217e8d8bef9SDimitry Andric 1218e8d8bef9SDimitry Andric bool Changed = false; 1219e8d8bef9SDimitry Andric DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F); 1220e8d8bef9SDimitry Andric auto &RI = AM.getResult<RegionInfoAnalysis>(F); 1221e8d8bef9SDimitry Andric std::vector<Region *> Regions; 1222e8d8bef9SDimitry Andric addRegionIntoQueue(*RI.getTopLevelRegion(), Regions); 1223e8d8bef9SDimitry Andric while (!Regions.empty()) { 1224e8d8bef9SDimitry Andric Region *R = Regions.back(); 1225e8d8bef9SDimitry Andric StructurizeCFG SCFG; 1226e8d8bef9SDimitry Andric SCFG.init(R); 1227e8d8bef9SDimitry Andric Changed |= SCFG.run(R, DT); 1228e8d8bef9SDimitry Andric Regions.pop_back(); 1229e8d8bef9SDimitry Andric } 1230e8d8bef9SDimitry Andric if (!Changed) 1231e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 1232e8d8bef9SDimitry Andric PreservedAnalyses PA; 1233e8d8bef9SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 1234e8d8bef9SDimitry Andric return PA; 12350b57cec5SDimitry Andric } 1236