53 #define DEBUG_TYPE "structurizecfg" 61 "structurizecfg-skip-uniform-regions",
63 cl::desc(
"Force whether the StructurizeCFG pass skips uniform regions"),
68 using BBValuePair = std::pair<BasicBlock *, Value *>;
90 class NearestCommonDominator {
93 bool ResultIsRemembered =
false;
99 ResultIsRemembered = Remember;
104 if (NewResult != Result)
105 ResultIsRemembered =
false;
107 ResultIsRemembered |= Remember;
112 explicit NearestCommonDominator(
DominatorTree *DomTree) : DT(DomTree) {}
128 bool resultIsRememberedBlock() {
return ResultIsRemembered; }
177 bool SkipUniformRegions;
194 BBPhiMap DeletedPhis;
195 BB2BBVecMap AddedPhis;
198 BranchVector Conditions;
202 BranchVector LoopConds;
209 unsigned getAdjustedLoopDepth(
RegionNode *RN);
221 void insertConditions(
bool Loops);
232 bool IncludeDominator);
246 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
248 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
257 explicit StructurizeCFG(
bool SkipUniformRegions_ =
false)
259 SkipUniformRegions(SkipUniformRegions_) {
261 SkipUniformRegions = ForceSkipUniformRegions.
getValue();
269 StringRef getPassName()
const override {
return "Structurize control flow"; }
272 if (SkipUniformRegions)
312 return LI->getLoopFor(SubRegion->
getExit());
315 return LI->getLoopFor(RN->
getEntry());
319 unsigned StructurizeCFG::getAdjustedLoopDepth(
RegionNode *RN) {
322 return LI->getLoopDepth(SubR->
getExit());
325 return LI->getLoopDepth(RN->
getEntry());
329 void StructurizeCFG::orderNodes() {
341 unsigned CurrentLoopDepth = 0;
342 Loop *CurrentLoop =
nullptr;
343 for (
auto I = RPOT.begin(),
E = RPOT.end();
I !=
E; ++
I) {
345 unsigned LoopDepth = getAdjustedLoopDepth(RN);
350 if (LoopDepth < CurrentLoopDepth) {
355 while (
unsigned &BlockCount = LoopBlocks[CurrentLoop]) {
357 if (getAdjustedLoop(cast<RegionNode>(*LoopI)) == CurrentLoop) {
359 Order.push_back(*LoopI);
364 CurrentLoop = getAdjustedLoop(RN);
366 LoopBlocks[CurrentLoop]--;
368 CurrentLoopDepth = LoopDepth;
384 if (Visited.count(Exit))
393 if (Visited.count(Succ))
399 Value *StructurizeCFG::invert(
Value *Condition) {
401 if (
Constant *
C = dyn_cast<Constant>(Condition))
409 if (
Instruction *Inst = dyn_cast<Instruction>(Condition)) {
421 if (
Argument *
Arg = dyn_cast<Argument>(Condition)) {
434 Value *Cond = Invert ? BoolFalse : BoolTrue;
438 if (Idx != (
unsigned)Invert)
445 void StructurizeCFG::gatherPredicates(
RegionNode *N) {
446 RegionInfo *RI = ParentRegion->getRegionInfo();
448 BBPredicates &Pred = Predicates[BB];
449 BBPredicates &LPred = LoopPreds[BB];
453 if (!ParentRegion->contains(
P))
457 if (R == ParentRegion) {
459 BranchInst *Term = cast<BranchInst>(
P->getTerminator());
465 if (Visited.count(
P)) {
470 if (Visited.count(Other) && !
Loops.count(Other) &&
471 !Pred.count(Other) && !Pred.count(
P)) {
473 Pred[Other] = BoolFalse;
478 Pred[
P] = buildCondition(Term, i,
false);
481 LPred[
P] = buildCondition(Term, i,
true);
494 if (Visited.count(Entry))
495 Pred[Entry] = BoolTrue;
497 LPred[Entry] = BoolFalse;
503 void StructurizeCFG::collectInfos() {
516 << (RN->
isSubRegion() ?
"SubRegion with entry: " :
"")
517 << RN->
getEntry()->getName() <<
" Loop Depth: " 518 << LI->getLoopDepth(RN->
getEntry()) <<
"\n");
521 gatherPredicates(RN);
532 void StructurizeCFG::insertConditions(
bool Loops) {
533 BranchVector &Conds = Loops ? LoopConds : Conditions;
534 Value *Default = Loops ? BoolTrue : BoolFalse;
548 BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue];
550 NearestCommonDominator Dominator(DT);
551 Dominator.addBlock(Parent);
553 Value *ParentValue =
nullptr;
554 for (std::pair<BasicBlock *, Value *> BBAndPred : Preds) {
556 Value *Pred = BBAndPred.second;
563 Dominator.addAndRememberBlock(BB);
569 if (!Dominator.resultIsRememberedBlock())
580 PhiMap &Map = DeletedPhis[To];
582 while (Phi.getBasicBlockIndex(From) != -1) {
584 Map[&Phi].push_back(std::make_pair(From, Deleted));
593 Phi.addIncoming(Undef, From);
595 AddedPhis[To].push_back(From);
599 void StructurizeCFG::setPhiValues() {
602 for (
const auto &AddedPhi : AddedPhis) {
604 const BBVector &From = AddedPhi.second;
606 if (!DeletedPhis.count(To))
609 PhiMap &Map = DeletedPhis[To];
610 for (
const auto &PI : Map) {
617 NearestCommonDominator Dominator(DT);
618 Dominator.addBlock(To);
619 for (
const auto &
VI : PI.second) {
621 Dominator.addAndRememberBlock(
VI.first);
624 if (!Dominator.resultIsRememberedBlock())
634 DeletedPhis.erase(To);
636 assert(DeletedPhis.empty());
645 for (
size_t i = 0; i < InsertedPhis.
size(); ++i) {
646 PHINode *Phi = InsertedPhis[i];
650 InsertedPhis[i] = InsertedPhis.
back();
660 void StructurizeCFG::killTerminator(
BasicBlock *BB) {
667 delPhiValues(BB, *
SI);
670 DA->removeValue(Term);
676 bool IncludeDominator) {
691 delPhiValues(BB, OldExit);
693 addPhiValues(BB, NewExit);
696 if (IncludeDominator) {
700 Dominator = DT->findNearestCommonDominator(Dominator, BB);
706 DT->changeImmediateDominator(NewExit, Dominator);
714 addPhiValues(BB, NewExit);
715 if (IncludeDominator)
716 DT->changeImmediateDominator(NewExit, BB);
723 BasicBlock *Insert = Order.empty() ? ParentRegion->getExit() :
724 Order.back()->getEntry();
727 DT->addNewBlock(Flow, Dominator);
728 ParentRegion->getRegionInfo()->setRegionFor(Flow, ParentRegion);
733 BasicBlock *StructurizeCFG::needPrefix(
bool NeedEmpty) {
736 if (!PrevNode->isSubRegion()) {
737 killTerminator(Entry);
746 changeExit(PrevNode, Flow,
true);
747 PrevNode = ParentRegion->getBBNode(Flow);
753 bool ExitUseAllowed) {
754 if (!Order.empty() || !ExitUseAllowed)
755 return getNextFlow(Flow);
758 DT->changeImmediateDominator(Exit, Flow);
759 addPhiValues(Flow, Exit);
764 void StructurizeCFG::setPrevNode(
BasicBlock *BB) {
765 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB)
771 BBPredicates &Preds = Predicates[Node->
getEntry()];
772 return llvm::all_of(Preds, [&](std::pair<BasicBlock *, Value *> Pred) {
773 return DT->dominates(BB, Pred.first);
778 bool StructurizeCFG::isPredictableTrue(
RegionNode *Node) {
779 BBPredicates &Preds = Predicates[Node->
getEntry()];
780 bool Dominated =
false;
786 for (std::pair<BasicBlock*, Value*> Pred : Preds) {
788 Value *V = Pred.second;
793 if (!Dominated && DT->dominates(BB, PrevNode->getEntry()))
802 void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
807 if (isPredictableTrue(Node)) {
810 changeExit(PrevNode, Node->
getEntry(),
true);
819 BasicBlock *Next = needPostfix(Flow, ExitUseAllowed);
823 addPhiValues(Flow, Entry);
824 DT->changeImmediateDominator(Entry, Flow);
827 while (!Order.empty() && !Visited.count(LoopEnd) &&
828 dominatesPredicates(Entry, Order.
back())) {
829 handleLoops(
false, LoopEnd);
832 changeExit(PrevNode, Next,
false);
837 void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
842 if (!Loops.count(LoopStart)) {
843 wireFlow(ExitUseAllowed, LoopEnd);
847 if (!isPredictableTrue(Node))
848 LoopStart = needPrefix(
true);
851 wireFlow(
false, LoopEnd);
852 while (!Visited.count(LoopEnd)) {
853 handleLoops(
false, LoopEnd);
860 LoopStart->
setName(
"entry.orig");
868 DT->setNewRoot(NewEntry);
872 LoopEnd = needPrefix(
false);
873 BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed);
875 BoolUndef, LoopEnd));
876 addPhiValues(LoopEnd, LoopStart);
882 void StructurizeCFG::createFlow() {
884 bool EntryDominatesExit = DT->dominates(ParentRegion->getEntry(), Exit);
894 while (!Order.empty()) {
895 handleLoops(EntryDominatesExit,
nullptr);
899 changeExit(PrevNode, Exit, EntryDominatesExit);
901 assert(EntryDominatesExit);
906 void StructurizeCFG::rebuildSSA() {
910 bool Initialized =
false;
913 for (
auto UI =
I.use_begin(),
E =
I.use_end(); UI !=
E;) {
918 }
else if (
PHINode *UserPN = dyn_cast<PHINode>(User)) {
919 if (UserPN->getIncomingBlock(U) == BB)
923 if (DT->dominates(&
I, User))
941 if (!
E->isSubRegion()) {
943 if (!Br || !Br->isConditional())
949 <<
" has uniform terminator\n");
962 if (!Br || !Br->isConditional())
965 if (!Br->getMetadata(UniformMDKindID))
980 if (SkipUniformRegions) {
985 unsigned UniformMDKindID =
986 R->
getEntry()->getContext().getMDKindID(
"structurizecfg.uniform");
987 DA = &getAnalysis<LegacyDivergenceAnalysis>();
990 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
999 if (
E->isSubRegion())
1002 if (
Instruction *Term =
E->getEntry()->getTerminator())
1013 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1014 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1019 insertConditions(
false);
1020 insertConditions(
true);
1027 DeletedPhis.clear();
1039 return new StructurizeCFG(SkipUniformRegions);
Pass interface - Implemented by all 'passes'.
T * getNodeAs() const
Get the content of this RegionNode.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static ConstantInt * getFalse(LLVMContext &Context)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static IntegerType * getInt1Ty(LLVMContext &C)
Helper class for SSA formation on a set of values defined in multiple blocks.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents an incoming formal argument to a Function.
static BinaryOperator * CreateNot(Value *Op, const Twine &Name="", Instruction *InsertBefore=nullptr)
This class represents lattice values for constants.
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value...
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B...
This class implements a map that also provides access to all stored values in a deterministic order...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
BasicBlock * getSuccessor(unsigned i) const
static const char *const FlowBlockName
Value * getCondition() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This defines the Use class.
BlockT * getExit() const
Get the exit BasicBlock of the Region.
bool isSubRegion() const
Is this RegionNode a subregion?
LLVMContext & getContext() const
Get the context in which this basic block lives.
The pass manager to schedule RegionPasses.
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
'undef' values are things that do not have specified contents.
unsigned getNumSuccessors() const
A Use represents the edge between a Value definition and its users.
void setName(const Twine &Name)
Change the name of the value.
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
User * getUser() const LLVM_READONLY
Returns the User that contains this Use.
block_range blocks()
Returns a range view of the basic blocks in the region.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
BlockT * getEntry() const
Get the entry BasicBlock of this RegionNode.
Type * getType() const
All values are typed, get the type of this value.
static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, const LegacyDivergenceAnalysis &DA)
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Interval::succ_iterator succ_end(Interval *I)
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
const BasicBlock & getEntryBlock() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
initializer< Ty > init(const Ty &Val)
Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block...
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
Conditional or Unconditional Branch instruction.
A pass that runs on each Region in a function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
void replaceExit(BlockT *BB)
Replace the exit basic block of the region with the new basic block.
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
int getNumOccurrences() const
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
Represent the analysis usage information of a pass.
const Instruction & back() const
Interval::pred_iterator pred_end(Interval *I)
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static Constant * getNot(Constant *C)
bool isTopLevelRegion() const
Check if a Region is the TopLevel region.
INITIALIZE_PASS_BEGIN(StructurizeCFG, "structurizecfg", "Structurize the CFG", false, false) INITIALIZE_PASS_END(StructurizeCFG
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
void initializeStructurizeCFGPass(PassRegistry &)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
BlockVerifier::State From
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
AnalysisUsage & addRequiredID(const void *ID)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
bool isConditional() const
pred_range predecessors(BasicBlock *BB)
static ConstantInt * getTrue(LLVMContext &Context)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
amdgpu Simplify well known AMD library false Value Value * Arg
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
Represents a single loop in the control flow graph.
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
void setCondition(Value *V)
RegionT * getParent() const
Get the parent of the Region.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
bool isUniform(const Value *V) const
The legacy pass manager's analysis pass to compute loop information.
StringRef - Represent a constant reference to a string, i.e.
Legacy analysis pass which computes a DominatorTree.
Value * GetValueAtEndOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live at the end of the specified block...
void setIncomingValue(unsigned i, Value *V)
Pass * createStructurizeCFGPass(bool SkipUniformRegions=false)
When SkipUniformRegions is true the structizer will not structurize regions that only contain uniform...
iterator_range< element_iterator > elements()
Value * SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, OptimizationRemarkEmitter *ORE=nullptr)
See if we can compute a simplified version of this instruction.
RegionT * getRegionFor(BlockT *BB) const
Get the smallest region that contains a BasicBlock.
BinaryOp_match< ValTy, cst_pred_ty< is_all_ones >, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
const BasicBlock * getParent() const
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.