diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp | 171 |
1 files changed, 109 insertions, 62 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp index c20e57b02c1a..3e15cad5f3f3 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Scalar/StructurizeCFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SCCIterator.h" @@ -28,6 +29,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" @@ -55,7 +57,7 @@ using namespace llvm::PatternMatch; #define DEBUG_TYPE "structurizecfg" // The name for newly created blocks. -static const char *const FlowBlockName = "Flow"; +const char FlowBlockName[] = "Flow"; namespace { @@ -233,9 +235,8 @@ public: /// while the true side continues the general flow. So the loop condition /// 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; +class StructurizeCFG { Type *Boolean; ConstantInt *BoolTrue; ConstantInt *BoolFalse; @@ -244,7 +245,7 @@ class StructurizeCFG : public RegionPass { Function *Func; Region *ParentRegion; - LegacyDivergenceAnalysis *DA; + LegacyDivergenceAnalysis *DA = nullptr; DominatorTree *DT; SmallVector<RegionNode *, 8> Order; @@ -309,19 +310,35 @@ class StructurizeCFG : public RegionPass { void rebuildSSA(); public: + void init(Region *R); + bool run(Region *R, DominatorTree *DT); + bool makeUniformRegion(Region *R, LegacyDivergenceAnalysis *DA); +}; + +class StructurizeCFGLegacyPass : public RegionPass { + bool SkipUniformRegions; + +public: static char ID; - explicit StructurizeCFG(bool SkipUniformRegions_ = false) - : RegionPass(ID), - SkipUniformRegions(SkipUniformRegions_) { + explicit StructurizeCFGLegacyPass(bool SkipUniformRegions_ = false) + : RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) { if (ForceSkipUniformRegions.getNumOccurrences()) SkipUniformRegions = ForceSkipUniformRegions.getValue(); - initializeStructurizeCFGPass(*PassRegistry::getPassRegistry()); + initializeStructurizeCFGLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool doInitialization(Region *R, RGPassManager &RGM) override; - - bool runOnRegion(Region *R, RGPassManager &RGM) override; + bool runOnRegion(Region *R, RGPassManager &RGM) override { + StructurizeCFG SCFG; + SCFG.init(R); + if (SkipUniformRegions) { + LegacyDivergenceAnalysis *DA = &getAnalysis<LegacyDivergenceAnalysis>(); + if (SCFG.makeUniformRegion(R, DA)) + return false; + } + DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + return SCFG.run(R, DT); + } StringRef getPassName() const override { return "Structurize control flow"; } @@ -338,28 +355,16 @@ public: } // end anonymous namespace -char StructurizeCFG::ID = 0; +char StructurizeCFGLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(StructurizeCFG, "structurizecfg", "Structurize the CFG", - false, false) +INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg", + "Structurize the CFG", false, false) INITIALIZE_PASS_DEPENDENCY(LegacyDivergenceAnalysis) -INITIALIZE_PASS_DEPENDENCY(LowerSwitch) +INITIALIZE_PASS_DEPENDENCY(LowerSwitchLegacyPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(RegionInfoPass) -INITIALIZE_PASS_END(StructurizeCFG, "structurizecfg", "Structurize the CFG", - false, false) - -/// Initialize the types and constants used in the pass -bool StructurizeCFG::doInitialization(Region *R, RGPassManager &RGM) { - LLVMContext &Context = R->getEntry()->getContext(); - - Boolean = Type::getInt1Ty(Context); - BoolTrue = ConstantInt::getTrue(Context); - BoolFalse = ConstantInt::getFalse(Context); - BoolUndef = UndefValue::get(Boolean); - - return false; -} +INITIALIZE_PASS_END(StructurizeCFGLegacyPass, "structurizecfg", + "Structurize the CFG", false, false) /// Build up the general order of nodes, by performing a topological sort of the /// parent region's nodes, while ensuring that there is no outer cycle node @@ -1003,48 +1008,62 @@ static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, return SubRegionsAreUniform || (ConditionalDirectChildren <= 1); } -/// Run the transformation for each region found -bool StructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) { +void StructurizeCFG::init(Region *R) { + LLVMContext &Context = R->getEntry()->getContext(); + + Boolean = Type::getInt1Ty(Context); + BoolTrue = ConstantInt::getTrue(Context); + BoolFalse = ConstantInt::getFalse(Context); + BoolUndef = UndefValue::get(Boolean); + + this->DA = nullptr; +} + +bool StructurizeCFG::makeUniformRegion(Region *R, + LegacyDivergenceAnalysis *DA) { if (R->isTopLevelRegion()) return false; - DA = nullptr; - - if (SkipUniformRegions) { - // TODO: We could probably be smarter here with how we handle sub-regions. - // We currently rely on the fact that metadata is set by earlier invocations - // of the pass on sub-regions, and that this metadata doesn't get lost -- - // but we shouldn't rely on metadata for correctness! - unsigned UniformMDKindID = - R->getEntry()->getContext().getMDKindID("structurizecfg.uniform"); - DA = &getAnalysis<LegacyDivergenceAnalysis>(); - - if (hasOnlyUniformBranches(R, UniformMDKindID, *DA)) { - LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R - << '\n'); - - // Mark all direct child block terminators as having been treated as - // uniform. To account for a possible future in which non-uniform - // sub-regions are treated more cleverly, indirect children are not - // marked as uniform. - MDNode *MD = MDNode::get(R->getEntry()->getParent()->getContext(), {}); - for (RegionNode *E : R->elements()) { - if (E->isSubRegion()) - continue; - - if (Instruction *Term = E->getEntry()->getTerminator()) - Term->setMetadata(UniformMDKindID, MD); - } + this->DA = DA; + // TODO: We could probably be smarter here with how we handle sub-regions. + // We currently rely on the fact that metadata is set by earlier invocations + // of the pass on sub-regions, and that this metadata doesn't get lost -- + // but we shouldn't rely on metadata for correctness! + unsigned UniformMDKindID = + R->getEntry()->getContext().getMDKindID("structurizecfg.uniform"); + + if (hasOnlyUniformBranches(R, UniformMDKindID, *DA)) { + LLVM_DEBUG(dbgs() << "Skipping region with uniform control flow: " << *R + << '\n'); + + // Mark all direct child block terminators as having been treated as + // uniform. To account for a possible future in which non-uniform + // sub-regions are treated more cleverly, indirect children are not + // marked as uniform. + MDNode *MD = MDNode::get(R->getEntry()->getParent()->getContext(), {}); + for (RegionNode *E : R->elements()) { + if (E->isSubRegion()) + continue; - return false; + if (Instruction *Term = E->getEntry()->getTerminator()) + Term->setMetadata(UniformMDKindID, MD); } + + return true; } + return false; +} + +/// Run the transformation for each region found +bool StructurizeCFG::run(Region *R, DominatorTree *DT) { + if (R->isTopLevelRegion()) + return false; + + this->DT = DT; Func = R->getEntry()->getParent(); ParentRegion = R; - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - orderNodes(); collectInfos(); createFlow(); @@ -1069,5 +1088,33 @@ bool StructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) { } Pass *llvm::createStructurizeCFGPass(bool SkipUniformRegions) { - return new StructurizeCFG(SkipUniformRegions); + return new StructurizeCFGLegacyPass(SkipUniformRegions); +} + +static void addRegionIntoQueue(Region &R, std::vector<Region *> &Regions) { + Regions.push_back(&R); + for (const auto &E : R) + addRegionIntoQueue(*E, Regions); +} + +PreservedAnalyses StructurizeCFGPass::run(Function &F, + FunctionAnalysisManager &AM) { + + bool Changed = false; + DominatorTree *DT = &AM.getResult<DominatorTreeAnalysis>(F); + auto &RI = AM.getResult<RegionInfoAnalysis>(F); + std::vector<Region *> Regions; + addRegionIntoQueue(*RI.getTopLevelRegion(), Regions); + while (!Regions.empty()) { + Region *R = Regions.back(); + StructurizeCFG SCFG; + SCFG.init(R); + Changed |= SCFG.run(R, DT); + Regions.pop_back(); + } + if (!Changed) + return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserve<DominatorTreeAnalysis>(); + return PA; } |