26 using namespace llvm::PatternMatch;
28 #define DEBUG_TYPE "structurizecfg"
34 typedef std::pair<BasicBlock *, Value *> BBValuePair;
52 static const char *
const FlowBlockName =
"Flow";
59 class NearestCommonDominator {
62 bool ResultIsRemembered =
false;
68 ResultIsRemembered = Remember;
72 BasicBlock *NewResult = DT->findNearestCommonDominator(Result, BB);
73 if (NewResult != Result)
74 ResultIsRemembered =
false;
76 ResultIsRemembered |= Remember;
81 explicit NearestCommonDominator(
DominatorTree *DomTree) : DT(DomTree) {}
97 bool resultIsRememberedBlock() {
return ResultIsRemembered; }
146 bool SkipUniformRegions;
162 BBPhiMap DeletedPhis;
163 BB2BBVecMap AddedPhis;
166 BranchVector Conditions;
170 BranchVector LoopConds;
186 void insertConditions(
bool Loops);
197 bool IncludeDominator);
211 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
213 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
222 explicit StructurizeCFG(
bool SkipUniformRegions =
false)
223 :
RegionPass(
ID), SkipUniformRegions(SkipUniformRegions) {
231 StringRef getPassName()
const override {
return "Structurize control flow"; }
234 if (SkipUniformRegions)
271 void StructurizeCFG::orderNodes() {
284 unsigned CurrentLoopDepth = 0;
285 Loop *CurrentLoop =
nullptr;
286 for (
auto I = RPOT.begin(),
E = RPOT.end();
I !=
E; ++
I) {
288 unsigned LoopDepth = LI->getLoopDepth(BB);
293 if (LoopDepth < CurrentLoopDepth) {
298 while (
unsigned &BlockCount = LoopBlocks[CurrentLoop]) {
301 if (LI->getLoopFor(LoopBB) == CurrentLoop) {
303 Order.push_back(*LoopI);
308 CurrentLoop = LI->getLoopFor(BB);
310 LoopBlocks[CurrentLoop]--;
312 CurrentLoopDepth = LoopDepth;
328 if (Visited.count(Exit))
337 if (Visited.count(Succ))
343 Value *StructurizeCFG::invert(
Value *Condition) {
345 if (
Constant *
C = dyn_cast<Constant>(Condition))
352 if (
Instruction *Inst = dyn_cast<Instruction>(Condition)) {
364 if (
Argument *Arg = dyn_cast<Argument>(Condition)) {
377 Value *Cond = Invert ? BoolFalse : BoolTrue;
381 if (Idx != (
unsigned)Invert)
388 void StructurizeCFG::gatherPredicates(
RegionNode *N) {
389 RegionInfo *RI = ParentRegion->getRegionInfo();
391 BBPredicates &Pred = Predicates[BB];
392 BBPredicates &LPred = LoopPreds[BB];
396 if (!ParentRegion->contains(
P))
400 if (R == ParentRegion) {
402 BranchInst *Term = cast<BranchInst>(
P->getTerminator());
408 if (Visited.count(
P)) {
413 if (Visited.count(Other) && !
Loops.count(Other) &&
414 !Pred.count(Other) && !Pred.count(
P)) {
416 Pred[Other] = BoolFalse;
421 Pred[
P] = buildCondition(Term,
i,
false);
424 LPred[
P] = buildCondition(Term,
i,
true);
437 if (Visited.count(Entry))
438 Pred[Entry] = BoolTrue;
440 LPred[Entry] = BoolFalse;
446 void StructurizeCFG::collectInfos() {
459 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
460 <<
RN->getEntry()->getName() <<
" Loop Depth: "
461 << LI->getLoopDepth(
RN->getEntry()) <<
"\n");
464 gatherPredicates(
RN);
467 Visited.insert(
RN->getEntry());
475 void StructurizeCFG::insertConditions(
bool Loops) {
476 BranchVector &Conds = Loops ? LoopConds : Conditions;
491 BBPredicates &Preds = Loops ? LoopPreds[SuccFalse] : Predicates[SuccTrue];
493 NearestCommonDominator Dominator(DT);
494 Dominator.addBlock(Parent);
496 Value *ParentValue =
nullptr;
497 for (std::pair<BasicBlock *, Value *> BBAndPred : Preds) {
499 Value *Pred = BBAndPred.second;
506 Dominator.addAndRememberBlock(BB);
512 if (!Dominator.resultIsRememberedBlock())
523 PhiMap &Map = DeletedPhis[To];
525 if (!isa<PHINode>(
I))
530 Map[&Phi].push_back(std::make_pair(From, Deleted));
538 if (!isa<PHINode>(
I))
544 AddedPhis[To].push_back(From);
548 void StructurizeCFG::setPhiValues() {
550 for (
const auto &AddedPhi : AddedPhis) {
552 const BBVector &From = AddedPhi.second;
554 if (!DeletedPhis.count(To))
557 PhiMap &Map = DeletedPhis[To];
558 for (
const auto &PI : Map) {
565 NearestCommonDominator Dominator(DT);
566 Dominator.addBlock(To);
567 for (
const auto &
VI : PI.second) {
569 Dominator.addAndRememberBlock(
VI.first);
572 if (!Dominator.resultIsRememberedBlock())
582 DeletedPhis.erase(To);
584 assert(DeletedPhis.empty());
588 void StructurizeCFG::killTerminator(
BasicBlock *BB) {
595 delPhiValues(BB, *SI);
602 bool IncludeDominator) {
617 delPhiValues(BB, OldExit);
619 addPhiValues(BB, NewExit);
622 if (IncludeDominator) {
626 Dominator = DT->findNearestCommonDominator(Dominator, BB);
632 DT->changeImmediateDominator(NewExit, Dominator);
640 addPhiValues(BB, NewExit);
641 if (IncludeDominator)
642 DT->changeImmediateDominator(NewExit, BB);
650 Order.back()->getEntry();
653 DT->addNewBlock(Flow, Dominator);
654 ParentRegion->getRegionInfo()->setRegionFor(Flow, ParentRegion);
659 BasicBlock *StructurizeCFG::needPrefix(
bool NeedEmpty) {
662 if (!PrevNode->isSubRegion()) {
663 killTerminator(Entry);
672 changeExit(PrevNode, Flow,
true);
673 PrevNode = ParentRegion->getBBNode(Flow);
679 bool ExitUseAllowed) {
680 if (!Order.empty() || !ExitUseAllowed)
681 return getNextFlow(Flow);
684 DT->changeImmediateDominator(Exit, Flow);
685 addPhiValues(Flow, Exit);
690 void StructurizeCFG::setPrevNode(
BasicBlock *BB) {
691 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB)
697 BBPredicates &Preds = Predicates[Node->
getEntry()];
698 return llvm::all_of(Preds, [&](std::pair<BasicBlock *, Value *> Pred) {
699 return DT->dominates(BB, Pred.first);
704 bool StructurizeCFG::isPredictableTrue(
RegionNode *Node) {
705 BBPredicates &Preds = Predicates[Node->
getEntry()];
706 bool Dominated =
false;
712 for (std::pair<BasicBlock*, Value*> Pred : Preds) {
714 Value *V = Pred.second;
719 if (!Dominated && DT->dominates(BB, PrevNode->getEntry()))
728 void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
733 if (isPredictableTrue(Node)) {
736 changeExit(PrevNode, Node->
getEntry(),
true);
746 BasicBlock *Next = needPostfix(Flow, ExitUseAllowed);
750 addPhiValues(Flow, Entry);
751 DT->changeImmediateDominator(Entry, Flow);
754 while (!Order.empty() && !Visited.count(LoopEnd) &&
755 dominatesPredicates(Entry, Order.
back())) {
756 handleLoops(
false, LoopEnd);
759 changeExit(PrevNode, Next,
false);
764 void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
769 if (!Loops.count(LoopStart)) {
770 wireFlow(ExitUseAllowed, LoopEnd);
774 if (!isPredictableTrue(Node))
775 LoopStart = needPrefix(
true);
778 wireFlow(
false, LoopEnd);
779 while (!Visited.count(LoopEnd)) {
780 handleLoops(
false, LoopEnd);
787 LoopStart->
setName(
"entry.orig");
795 DT->setNewRoot(NewEntry);
799 LoopEnd = needPrefix(
false);
800 BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed);
802 BoolUndef, LoopEnd));
803 addPhiValues(LoopEnd, LoopStart);
809 void StructurizeCFG::createFlow() {
811 bool EntryDominatesExit = DT->dominates(ParentRegion->getEntry(), Exit);
821 while (!Order.empty()) {
822 handleLoops(EntryDominatesExit,
nullptr);
826 changeExit(PrevNode, Exit, EntryDominatesExit);
828 assert(EntryDominatesExit);
833 void StructurizeCFG::rebuildSSA() {
837 bool Initialized =
false;
840 for (
auto UI =
I.use_begin(),
E =
I.use_end(); UI !=
E;) {
845 }
else if (
PHINode *UserPN = dyn_cast<PHINode>(User)) {
846 if (UserPN->getIncomingBlock(U) == BB)
850 if (DT->dominates(&
I, User))
874 DEBUG(
dbgs() <<
"BB: " << BB->getName() <<
" has uniform terminator\n");
884 if (SkipUniformRegions) {
886 auto &DA = getAnalysis<DivergenceAnalysis>();
888 DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R <<
'\n');
896 if (
E->isSubRegion())
910 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
911 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
916 insertConditions(
false);
917 insertConditions(
true);
936 return new StructurizeCFG(SkipUniformRegions);
Pass interface - Implemented by all 'passes'.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
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.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM Argument representation.
static BinaryOperator * CreateNot(Value *Op, const Twine &Name="", Instruction *InsertBefore=nullptr)
const Instruction & back() const
iterator_range< element_iterator > elements()
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...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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...
const Function * getParent() const
Return the enclosing method, or null if none.
BlockT * getEntry() const
Get the entry BasicBlock of this RegionNode.
bool isSubRegion() const
Is this RegionNode a subregion?
T * getNodeAs() const
Get the content of this RegionNode.
The pass manager to schedule RegionPasses.
RegionT * getRegionFor(BlockT *BB) const
Get the smallest region that contains a BasicBlock.
StringRef getName() const
Return a constant reference to the value's name.
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static bool hasOnlyUniformBranches(const Region *R, const DivergenceAnalysis &DA)
Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)
Remove an incoming value.
'undef' values are things that do not have specified contents.
A Use represents the edge between a Value definition and its users.
RegionT * getParent() const
Get the parent of the Region.
void setName(const Twine &Name)
Change the name of the value.
block_range blocks()
Returns a range view of the basic blocks in the region.
INITIALIZE_PASS_BEGIN(StructurizeCFG,"structurizecfg","Structurize the CFG", false, false) INITIALIZE_PASS_END(StructurizeCFG
not_match< LHS > m_Not(const LHS &L)
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()))
BasicBlock * getSuccessor(unsigned i) const
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
Interval::succ_iterator succ_end(Interval *I)
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block...
Subclasses of this class are all able to terminate a basic block.
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.
This is an important base class in LLVM.
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...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
User * getUser() const
Returns the User that contains this Use.
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)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
void initializeStructurizeCFGPass(PassRegistry &)
#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.
bool isConditional() const
bool isUniform(const Value *V) const
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.
AnalysisUsage & addRequiredID(const void *ID)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
pred_range predecessors(BasicBlock *BB)
const BasicBlock & getEntryBlock() const
static ConstantInt * getTrue(LLVMContext &Context)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Value * getCondition() const
unsigned getNumSuccessors() const
Represents a single loop in the control flow graph.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void setCondition(Value *V)
BlockT * getExit() const
Get the exit BasicBlock of the Region.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVMContext & getContext() const
Get the context in which this basic block lives.
LLVM Value Representation.
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
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.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
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...
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
const BasicBlock * getParent() const
bool isTopLevelRegion() const
Check if a Region is the TopLevel region.
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.