6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
9
+ #include " llvm/Transforms/Scalar/StructurizeCFG.h"
9
10
#include " llvm/ADT/DenseMap.h"
10
11
#include " llvm/ADT/MapVector.h"
11
12
#include " llvm/ADT/SCCIterator.h"
28
29
#include " llvm/IR/Instruction.h"
29
30
#include " llvm/IR/Instructions.h"
30
31
#include " llvm/IR/Metadata.h"
32
+ #include " llvm/IR/PassManager.h"
31
33
#include " llvm/IR/PatternMatch.h"
32
34
#include " llvm/IR/Type.h"
33
35
#include " llvm/IR/Use.h"
@@ -233,9 +235,8 @@ class NearestCommonDominator {
233
235
// / while the true side continues the general flow. So the loop condition
234
236
// / consist of a network of PHI nodes where the true incoming values expresses
235
237
// / breaks and the false values expresses continue states.
236
- class StructurizeCFG : public RegionPass {
237
- bool SkipUniformRegions;
238
238
239
+ class StructurizeCFG {
239
240
Type *Boolean;
240
241
ConstantInt *BoolTrue;
241
242
ConstantInt *BoolFalse;
@@ -244,7 +245,7 @@ class StructurizeCFG : public RegionPass {
244
245
Function *Func;
245
246
Region *ParentRegion;
246
247
247
- LegacyDivergenceAnalysis *DA;
248
+ LegacyDivergenceAnalysis *DA = nullptr ;
248
249
DominatorTree *DT;
249
250
250
251
SmallVector<RegionNode *, 8 > Order;
@@ -308,20 +309,36 @@ class StructurizeCFG : public RegionPass {
308
309
309
310
void rebuildSSA ();
310
311
312
+ public:
313
+ void init (Region *R);
314
+ bool run (Region *R, DominatorTree *DT);
315
+ bool makeUniformRegion (Region *R, LegacyDivergenceAnalysis *DA);
316
+ };
317
+
318
+ class StructurizeCFGLegacyPass : public RegionPass {
319
+ bool SkipUniformRegions;
320
+
311
321
public:
312
322
static char ID;
313
323
314
- explicit StructurizeCFG (bool SkipUniformRegions_ = false )
315
- : RegionPass(ID),
316
- SkipUniformRegions(SkipUniformRegions_) {
324
+ explicit StructurizeCFGLegacyPass (bool SkipUniformRegions_ = false )
325
+ : RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) {
317
326
if (ForceSkipUniformRegions.getNumOccurrences ())
318
327
SkipUniformRegions = ForceSkipUniformRegions.getValue ();
319
- initializeStructurizeCFGPass (*PassRegistry::getPassRegistry ());
328
+ initializeStructurizeCFGLegacyPassPass (*PassRegistry::getPassRegistry ());
320
329
}
321
330
322
- bool doInitialization (Region *R, RGPassManager &RGM) override ;
323
-
324
- bool runOnRegion (Region *R, RGPassManager &RGM) override ;
331
+ bool runOnRegion (Region *R, RGPassManager &RGM) override {
332
+ StructurizeCFG SCFG;
333
+ SCFG.init (R);
334
+ if (SkipUniformRegions) {
335
+ LegacyDivergenceAnalysis *DA = &getAnalysis<LegacyDivergenceAnalysis>();
336
+ if (SCFG.makeUniformRegion (R, DA))
337
+ return false ;
338
+ }
339
+ DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree ();
340
+ return SCFG.run (R, DT);
341
+ }
325
342
326
343
StringRef getPassName () const override { return " Structurize control flow" ; }
327
344
@@ -338,28 +355,16 @@ class StructurizeCFG : public RegionPass {
338
355
339
356
} // end anonymous namespace
340
357
341
- char StructurizeCFG ::ID = 0 ;
358
+ char StructurizeCFGLegacyPass ::ID = 0 ;
342
359
343
- INITIALIZE_PASS_BEGIN (StructurizeCFG , " structurizecfg" , " Structurize the CFG " ,
344
- false , false )
360
+ INITIALIZE_PASS_BEGIN (StructurizeCFGLegacyPass , " structurizecfg" ,
361
+ " Structurize the CFG " , false , false )
345
362
INITIALIZE_PASS_DEPENDENCY(LegacyDivergenceAnalysis)
346
363
INITIALIZE_PASS_DEPENDENCY(LowerSwitchLegacyPass)
347
364
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
348
365
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass)
349
- INITIALIZE_PASS_END(StructurizeCFG, " structurizecfg" , " Structurize the CFG" ,
350
- false , false )
351
-
352
- // / Initialize the types and constants used in the pass
353
- bool StructurizeCFG::doInitialization(Region *R, RGPassManager &RGM) {
354
- LLVMContext &Context = R->getEntry ()->getContext ();
355
-
356
- Boolean = Type::getInt1Ty (Context);
357
- BoolTrue = ConstantInt::getTrue (Context);
358
- BoolFalse = ConstantInt::getFalse (Context);
359
- BoolUndef = UndefValue::get (Boolean);
360
-
361
- return false ;
362
- }
366
+ INITIALIZE_PASS_END(StructurizeCFGLegacyPass, " structurizecfg" ,
367
+ " Structurize the CFG" , false , false )
363
368
364
369
// / Build up the general order of nodes, by performing a topological sort of the
365
370
// / parent region's nodes, while ensuring that there is no outer cycle node
@@ -1003,48 +1008,62 @@ static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID,
1003
1008
return SubRegionsAreUniform || (ConditionalDirectChildren <= 1 );
1004
1009
}
1005
1010
1006
- // / Run the transformation for each region found
1007
- bool StructurizeCFG::runOnRegion (Region *R, RGPassManager &RGM) {
1011
+ void StructurizeCFG::init (Region *R) {
1012
+ LLVMContext &Context = R->getEntry ()->getContext ();
1013
+
1014
+ Boolean = Type::getInt1Ty (Context);
1015
+ BoolTrue = ConstantInt::getTrue (Context);
1016
+ BoolFalse = ConstantInt::getFalse (Context);
1017
+ BoolUndef = UndefValue::get (Boolean);
1018
+
1019
+ this ->DA = nullptr ;
1020
+ }
1021
+
1022
+ bool StructurizeCFG::makeUniformRegion (Region *R,
1023
+ LegacyDivergenceAnalysis *DA) {
1008
1024
if (R->isTopLevelRegion ())
1009
1025
return false ;
1010
1026
1011
- DA = nullptr ;
1012
-
1013
- if (SkipUniformRegions) {
1014
- // TODO: We could probably be smarter here with how we handle sub-regions.
1015
- // We currently rely on the fact that metadata is set by earlier invocations
1016
- // of the pass on sub-regions, and that this metadata doesn't get lost --
1017
- // but we shouldn't rely on metadata for correctness!
1018
- unsigned UniformMDKindID =
1019
- R->getEntry ()->getContext ().getMDKindID (" structurizecfg.uniform" );
1020
- DA = &getAnalysis<LegacyDivergenceAnalysis>();
1021
-
1022
- if (hasOnlyUniformBranches (R, UniformMDKindID, *DA)) {
1023
- LLVM_DEBUG (dbgs () << " Skipping region with uniform control flow: " << *R
1024
- << ' \n ' );
1025
-
1026
- // Mark all direct child block terminators as having been treated as
1027
- // uniform. To account for a possible future in which non-uniform
1028
- // sub-regions are treated more cleverly, indirect children are not
1029
- // marked as uniform.
1030
- MDNode *MD = MDNode::get (R->getEntry ()->getParent ()->getContext (), {});
1031
- for (RegionNode *E : R->elements ()) {
1032
- if (E->isSubRegion ())
1033
- continue ;
1034
-
1035
- if (Instruction *Term = E->getEntry ()->getTerminator ())
1036
- Term->setMetadata (UniformMDKindID, MD);
1037
- }
1027
+ this ->DA = DA;
1028
+ // TODO: We could probably be smarter here with how we handle sub-regions.
1029
+ // We currently rely on the fact that metadata is set by earlier invocations
1030
+ // of the pass on sub-regions, and that this metadata doesn't get lost --
1031
+ // but we shouldn't rely on metadata for correctness!
1032
+ unsigned UniformMDKindID =
1033
+ R->getEntry ()->getContext ().getMDKindID (" structurizecfg.uniform" );
1034
+
1035
+ if (hasOnlyUniformBranches (R, UniformMDKindID, *DA)) {
1036
+ LLVM_DEBUG (dbgs () << " Skipping region with uniform control flow: " << *R
1037
+ << ' \n ' );
1038
+
1039
+ // Mark all direct child block terminators as having been treated as
1040
+ // uniform. To account for a possible future in which non-uniform
1041
+ // sub-regions are treated more cleverly, indirect children are not
1042
+ // marked as uniform.
1043
+ MDNode *MD = MDNode::get (R->getEntry ()->getParent ()->getContext (), {});
1044
+ for (RegionNode *E : R->elements ()) {
1045
+ if (E->isSubRegion ())
1046
+ continue ;
1038
1047
1039
- return false ;
1048
+ if (Instruction *Term = E->getEntry ()->getTerminator ())
1049
+ Term->setMetadata (UniformMDKindID, MD);
1040
1050
}
1051
+
1052
+ return true ;
1041
1053
}
1054
+ return false ;
1055
+ }
1056
+
1057
+ // / Run the transformation for each region found
1058
+ bool StructurizeCFG::run (Region *R, DominatorTree *DT) {
1059
+ if (R->isTopLevelRegion ())
1060
+ return false ;
1061
+
1062
+ this ->DT = DT;
1042
1063
1043
1064
Func = R->getEntry ()->getParent ();
1044
1065
ParentRegion = R;
1045
1066
1046
- DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree ();
1047
-
1048
1067
orderNodes ();
1049
1068
collectInfos ();
1050
1069
createFlow ();
@@ -1069,5 +1088,33 @@ bool StructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) {
1069
1088
}
1070
1089
1071
1090
Pass *llvm::createStructurizeCFGPass (bool SkipUniformRegions) {
1072
- return new StructurizeCFG (SkipUniformRegions);
1091
+ return new StructurizeCFGLegacyPass (SkipUniformRegions);
1092
+ }
1093
+
1094
+ static void addRegionIntoQueue (Region &R, std::vector<Region *> &Regions) {
1095
+ Regions.push_back (&R);
1096
+ for (const auto &E : R)
1097
+ addRegionIntoQueue (*E, Regions);
1098
+ }
1099
+
1100
+ PreservedAnalyses StructurizeCFGPass::run (Function &F,
1101
+ FunctionAnalysisManager &AM) {
1102
+
1103
+ bool Changed = false ;
1104
+ DominatorTree *DT = &AM.getResult <DominatorTreeAnalysis>(F);
1105
+ auto &RI = AM.getResult <RegionInfoAnalysis>(F);
1106
+ std::vector<Region *> Regions;
1107
+ addRegionIntoQueue (*RI.getTopLevelRegion (), Regions);
1108
+ while (!Regions.empty ()) {
1109
+ Region *R = Regions.back ();
1110
+ StructurizeCFG SCFG;
1111
+ SCFG.init (R);
1112
+ Changed |= SCFG.run (R, DT);
1113
+ Regions.pop_back ();
1114
+ }
1115
+ if (!Changed)
1116
+ return PreservedAnalyses::all ();
1117
+ PreservedAnalyses PA;
1118
+ PA.preserve <DominatorTreeAnalysis>();
1119
+ return PA;
1073
1120
}
0 commit comments