Skip to content

Commit baffd05

Browse files
committed
[StructurizeCFG][NewPM] Port -structurizecfg to NPM
This doesn't support -structurizecfg-skip-uniform-regions since that would require porting LegacyDivergenceAnalysis. The NPM doesn't support adding a non-analysis pass as a dependency of another, so I had to add -lowerswitch to some tests or pin them to the legacy PM. This is the only RegionPass in tree, so I simply copied the logic for finding all Regions from the legacy PM's RGManager into StructurizeCFG::run(). Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D89026
1 parent ba22c40 commit baffd05

File tree

10 files changed

+135
-65
lines changed

10 files changed

+135
-65
lines changed

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ void initializeStripGCRelocatesLegacyPass(PassRegistry &);
418418
void initializeStripNonDebugSymbolsPass(PassRegistry&);
419419
void initializeStripNonLineTableDebugLegacyPassPass(PassRegistry &);
420420
void initializeStripSymbolsPass(PassRegistry&);
421-
void initializeStructurizeCFGPass(PassRegistry&);
421+
void initializeStructurizeCFGLegacyPassPass(PassRegistry &);
422422
void initializeTailCallElimPass(PassRegistry&);
423423
void initializeTailDuplicatePass(PassRegistry&);
424424
void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===- StructurizeCFG.h ---------------------------------------------------===//
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+
#ifndef LLVM_TRANSFORMS_SCALAR_STRUCTURIZECFG_H
10+
#define LLVM_TRANSFORMS_SCALAR_STRUCTURIZECFG_H
11+
12+
#include "llvm/IR/PassManager.h"
13+
14+
namespace llvm {
15+
struct StructurizeCFGPass : PassInfoMixin<StructurizeCFGPass> {
16+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
17+
};
18+
} // namespace llvm
19+
20+
#endif // LLVM_TRANSFORMS_SCALAR_STRUCTURIZECFG_H

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
#include "llvm/Transforms/Scalar/Sink.h"
192192
#include "llvm/Transforms/Scalar/SpeculateAroundPHIs.h"
193193
#include "llvm/Transforms/Scalar/SpeculativeExecution.h"
194+
#include "llvm/Transforms/Scalar/StructurizeCFG.h"
194195
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
195196
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
196197
#include "llvm/Transforms/Utils/AddDiscriminators.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ FUNCTION_PASS("speculative-execution", SpeculativeExecutionPass())
287287
FUNCTION_PASS("spec-phis", SpeculateAroundPHIsPass())
288288
FUNCTION_PASS("sroa", SROA())
289289
FUNCTION_PASS("strip-gc-relocates", StripGCRelocates())
290+
FUNCTION_PASS("structurizecfg", StructurizeCFGPass())
290291
FUNCTION_PASS("tailcallelim", TailCallElimPass())
291292
FUNCTION_PASS("unify-loop-exits", UnifyLoopExitsPass())
292293
FUNCTION_PASS("vector-combine", VectorCombinePass())

llvm/lib/Transforms/Scalar/Scalar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) {
9797
initializeSCCPLegacyPassPass(Registry);
9898
initializeSROALegacyPassPass(Registry);
9999
initializeCFGSimplifyPassPass(Registry);
100-
initializeStructurizeCFGPass(Registry);
100+
initializeStructurizeCFGLegacyPassPass(Registry);
101101
initializeSimpleLoopUnswitchLegacyPassPass(Registry);
102102
initializeSinkingLegacyPassPass(Registry);
103103
initializeTailCallElimPass(Registry);

llvm/lib/Transforms/Scalar/StructurizeCFG.cpp

Lines changed: 107 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/Transforms/Scalar/StructurizeCFG.h"
910
#include "llvm/ADT/DenseMap.h"
1011
#include "llvm/ADT/MapVector.h"
1112
#include "llvm/ADT/SCCIterator.h"
@@ -28,6 +29,7 @@
2829
#include "llvm/IR/Instruction.h"
2930
#include "llvm/IR/Instructions.h"
3031
#include "llvm/IR/Metadata.h"
32+
#include "llvm/IR/PassManager.h"
3133
#include "llvm/IR/PatternMatch.h"
3234
#include "llvm/IR/Type.h"
3335
#include "llvm/IR/Use.h"
@@ -233,9 +235,8 @@ class NearestCommonDominator {
233235
/// while the true side continues the general flow. So the loop condition
234236
/// consist of a network of PHI nodes where the true incoming values expresses
235237
/// breaks and the false values expresses continue states.
236-
class StructurizeCFG : public RegionPass {
237-
bool SkipUniformRegions;
238238

239+
class StructurizeCFG {
239240
Type *Boolean;
240241
ConstantInt *BoolTrue;
241242
ConstantInt *BoolFalse;
@@ -244,7 +245,7 @@ class StructurizeCFG : public RegionPass {
244245
Function *Func;
245246
Region *ParentRegion;
246247

247-
LegacyDivergenceAnalysis *DA;
248+
LegacyDivergenceAnalysis *DA = nullptr;
248249
DominatorTree *DT;
249250

250251
SmallVector<RegionNode *, 8> Order;
@@ -308,20 +309,36 @@ class StructurizeCFG : public RegionPass {
308309

309310
void rebuildSSA();
310311

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+
311321
public:
312322
static char ID;
313323

314-
explicit StructurizeCFG(bool SkipUniformRegions_ = false)
315-
: RegionPass(ID),
316-
SkipUniformRegions(SkipUniformRegions_) {
324+
explicit StructurizeCFGLegacyPass(bool SkipUniformRegions_ = false)
325+
: RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) {
317326
if (ForceSkipUniformRegions.getNumOccurrences())
318327
SkipUniformRegions = ForceSkipUniformRegions.getValue();
319-
initializeStructurizeCFGPass(*PassRegistry::getPassRegistry());
328+
initializeStructurizeCFGLegacyPassPass(*PassRegistry::getPassRegistry());
320329
}
321330

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+
}
325342

326343
StringRef getPassName() const override { return "Structurize control flow"; }
327344

@@ -338,28 +355,16 @@ class StructurizeCFG : public RegionPass {
338355

339356
} // end anonymous namespace
340357

341-
char StructurizeCFG::ID = 0;
358+
char StructurizeCFGLegacyPass::ID = 0;
342359

343-
INITIALIZE_PASS_BEGIN(StructurizeCFG, "structurizecfg", "Structurize the CFG",
344-
false, false)
360+
INITIALIZE_PASS_BEGIN(StructurizeCFGLegacyPass, "structurizecfg",
361+
"Structurize the CFG", false, false)
345362
INITIALIZE_PASS_DEPENDENCY(LegacyDivergenceAnalysis)
346363
INITIALIZE_PASS_DEPENDENCY(LowerSwitchLegacyPass)
347364
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
348365
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)
363368

364369
/// Build up the general order of nodes, by performing a topological sort of the
365370
/// parent region's nodes, while ensuring that there is no outer cycle node
@@ -1003,48 +1008,62 @@ static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID,
10031008
return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
10041009
}
10051010

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) {
10081024
if (R->isTopLevelRegion())
10091025
return false;
10101026

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;
10381047

1039-
return false;
1048+
if (Instruction *Term = E->getEntry()->getTerminator())
1049+
Term->setMetadata(UniformMDKindID, MD);
10401050
}
1051+
1052+
return true;
10411053
}
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;
10421063

10431064
Func = R->getEntry()->getParent();
10441065
ParentRegion = R;
10451066

1046-
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1047-
10481067
orderNodes();
10491068
collectInfos();
10501069
createFlow();
@@ -1069,5 +1088,33 @@ bool StructurizeCFG::runOnRegion(Region *R, RGPassManager &RGM) {
10691088
}
10701089

10711090
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;
10731120
}

llvm/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt -mtriple=amdgcn-- -S -o - -structurizecfg -structurizecfg-skip-uniform-regions -structurizecfg-relaxed-uniform-regions < %s | FileCheck %s
2+
; RUN: opt -mtriple=amdgcn-- -S -o - -structurizecfg -structurizecfg-skip-uniform-regions -structurizecfg-relaxed-uniform-regions -enable-new-pm=0 < %s | FileCheck %s
33

44
define amdgpu_cs void @uniform(i32 inreg %v) {
55
; CHECK-LABEL: @uniform(

llvm/test/Transforms/StructurizeCFG/interleaved-loop-order.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
2+
; RUN: opt -S -lowerswitch -structurizecfg %s -o - | FileCheck %s
33

44
; This test have an outer loop containing an inner loop,
55
; for which there is an interleaved post-order traversal.

llvm/test/Transforms/StructurizeCFG/nested-loop-order.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
2+
; RUN: opt -S -passes=structurizecfg %s -o - | FileCheck %s
23

34
define void @main(float addrspace(1)* %out) {
45

llvm/test/Transforms/StructurizeCFG/switch.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
1+
; RUN: opt -S -structurizecfg %s -o - -enable-new-pm=0 | FileCheck %s
22

33
; The structurizecfg pass cannot handle switch instructions, so we need to
44
; make sure the lower switch pass is always run before structurizecfg.

0 commit comments

Comments
 (0)