Index: include/llvm/Transforms/Scalar.h =================================================================== --- include/llvm/Transforms/Scalar.h +++ include/llvm/Transforms/Scalar.h @@ -262,7 +262,10 @@ // // CFG Structurization - Remove irreducible control flow // -Pass *createStructurizeCFGPass(); +/// +/// When \p SkipUniformRegions is true the structizer will not structurize +/// regions that only contain uniform branches. +Pass *createStructurizeCFGPass(bool SkipUniformRegions = false); //===----------------------------------------------------------------------===// // Index: lib/Transforms/Scalar/StructurizeCFG.cpp =================================================================== --- lib/Transforms/Scalar/StructurizeCFG.cpp +++ lib/Transforms/Scalar/StructurizeCFG.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SCCIterator.h" +#include "llvm/Analysis/DivergenceAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" @@ -161,6 +162,9 @@ /// consist of a network of PHI nodes where the true incoming values expresses /// breaks and the false values expresses continue states. class StructurizeCFG : public RegionPass { + bool SkipUniformRegions; + DivergenceAnalysis *DA; + Type *Boolean; ConstantInt *BoolTrue; ConstantInt *BoolFalse; @@ -232,6 +236,8 @@ void rebuildSSA(); + bool hasOnlyUniformBranches(const Region *R); + public: static char ID; @@ -240,6 +246,11 @@ initializeStructurizeCFGPass(*PassRegistry::getPassRegistry()); } + StructurizeCFG(bool SkipUniformRegions) : + RegionPass(ID), SkipUniformRegions(SkipUniformRegions) { + initializeStructurizeCFGPass(*PassRegistry::getPassRegistry()); + } + using Pass::doInitialization; bool doInitialization(Region *R, RGPassManager &RGM) override; @@ -250,6 +261,7 @@ } void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); AU.addRequiredID(LowerSwitchID); AU.addRequired(); AU.addRequired(); @@ -264,6 +276,7 @@ INITIALIZE_PASS_BEGIN(StructurizeCFG, "structurizecfg", "Structurize the CFG", false, false) +INITIALIZE_PASS_DEPENDENCY(DivergenceAnalysis) INITIALIZE_PASS_DEPENDENCY(LowerSwitch) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(RegionInfoPass) @@ -914,11 +927,33 @@ } } +bool StructurizeCFG::hasOnlyUniformBranches(const Region *R) { + for (const BasicBlock *BB : R->blocks()) { + const BranchInst *Br = dyn_cast(BB->getTerminator()); + if (!Br || !Br->isConditional()) + continue; + + if (!DA->isUniform(Br->getCondition())) + return false; + DEBUG(dbgs() << "BB: " << BB->getName() << " has uniform terminator\n"); + } + return true; +} + /// \brief Run the transformation for each region found bool StructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) { if (R->isTopLevelRegion()) return false; + if (SkipUniformRegions) { + DA = &getAnalysis(); + // TODO: We could probably be smarter here with how we handle sub-regions. + if (hasOnlyUniformBranches(R)) { + DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R << '\n'); + return false; + } + } + Func = R->getEntry()->getParent(); ParentRegion = R; @@ -947,7 +982,6 @@ return true; } -/// \brief Create the pass -Pass *llvm::createStructurizeCFGPass() { - return new StructurizeCFG(); +Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) { + return new StructurizeCFG(SkipUniformRegions); }