56#define DEBUG_TYPE "structurizecfg"
64 "structurizecfg-skip-uniform-regions",
66 cl::desc(
"Force whether the StructurizeCFG pass skips uniform regions"),
70 RelaxedUniformRegions(
"structurizecfg-relaxed-uniform-regions",
cl::Hidden,
71 cl::desc(
"Allow relaxed uniform region checks"),
76using BBValuePair = std::pair<BasicBlock *, Value *>;
90using MaybeCondBranchWeights = std::optional<class CondBranchWeights>;
92class CondBranchWeights {
99 static MaybeCondBranchWeights tryParse(
const BranchInst &Br) {
106 return CondBranchWeights(
T,
F);
110 const MaybeCondBranchWeights &Weights) {
114 uint32_t Arr[] = {Weights->TrueWeight, Weights->FalseWeight};
118 CondBranchWeights invert()
const {
119 return CondBranchWeights{FalseWeight, TrueWeight};
125 MaybeCondBranchWeights Weights;
137struct SubGraphTraits {
138 using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>;
143 class WrappedSuccIterator
145 WrappedSuccIterator, BaseSuccIterator,
146 typename std::iterator_traits<BaseSuccIterator>::iterator_category,
147 NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> {
154 NodeRef
operator*()
const {
return {*
I, Nodes}; }
157 static bool filterAll(
const NodeRef &
N) {
return true; }
158 static bool filterSet(
const NodeRef &
N) {
return N.second->count(
N.first); }
160 using ChildIteratorType =
163 static NodeRef getEntryNode(
Region *R) {
167 static NodeRef getEntryNode(NodeRef
N) {
return N; }
170 auto *filter =
N.second ? &filterSet : &filterAll;
172 make_range<WrappedSuccIterator>(
178 static ChildIteratorType child_begin(
const NodeRef &
N) {
182 static ChildIteratorType child_end(
const NodeRef &
N) {
192class NearestCommonDominator {
195 bool ResultIsRemembered =
false;
198 void addBlock(
BasicBlock *BB,
bool Remember) {
201 ResultIsRemembered = Remember;
206 if (NewResult != Result)
207 ResultIsRemembered =
false;
209 ResultIsRemembered |= Remember;
214 explicit NearestCommonDominator(
DominatorTree *DomTree) : DT(DomTree) {}
230 bool resultIsRememberedBlock() {
return ResultIsRemembered; }
279class StructurizeCFG {
296 BBPhiMap DeletedPhis;
297 BB2BBVecMap AddedPhis;
300 BranchVector Conditions;
304 BranchVector LoopConds;
306 BranchDebugLocMap TermDL;
314 PredInfo buildCondition(
BranchInst *Term,
unsigned Idx,
bool Invert);
320 void insertConditions(
bool Loops);
322 void simplifyConditions();
337 void simplifyAffectedPhis();
342 bool IncludeDominator);
356 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
358 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
370class StructurizeCFGLegacyPass :
public RegionPass {
371 bool SkipUniformRegions;
376 explicit StructurizeCFGLegacyPass(
bool SkipUniformRegions_ =
false)
377 :
RegionPass(
ID), SkipUniformRegions(SkipUniformRegions_) {
379 SkipUniformRegions = ForceSkipUniformRegions.
getValue();
386 if (SkipUniformRegions) {
388 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
389 if (SCFG.makeUniformRegion(R, UA))
392 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
393 return SCFG.run(R, DT);
399 if (SkipUniformRegions)
410char StructurizeCFGLegacyPass::ID = 0;
413 "Structurize the CFG",
false,
false)
423void StructurizeCFG::orderNodes() {
430 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
434 unsigned I = 0, E = Order.size();
446 unsigned Size = SCC.size();
451 for (
const auto &
N : SCC) {
452 assert(
I < E &&
"SCC size mismatch!");
453 Order[
I++] =
N.first;
456 assert(
I == E &&
"SCC size mismatch!");
459 if (WorkList.
empty())
468 Nodes.
insert(Order.begin() +
I, Order.begin() + E - 1);
471 EntryNode.first = Order[E - 1];
472 EntryNode.second = &Nodes;
478 if (
N->isSubRegion()) {
481 if (Visited.count(Exit))
490 if (Visited.count(Succ))
496PredInfo StructurizeCFG::buildCondition(
BranchInst *Term,
unsigned Idx,
498 Value *
Cond = Invert ? BoolFalse : BoolTrue;
499 MaybeCondBranchWeights Weights;
501 if (
Term->isConditional()) {
503 Weights = CondBranchWeights::tryParse(*Term);
505 if (
Idx != (
unsigned)Invert) {
508 Weights = Weights->invert();
511 return {
Cond, Weights};
515void StructurizeCFG::gatherPredicates(
RegionNode *
N) {
516 RegionInfo *RI = ParentRegion->getRegionInfo();
523 if (!ParentRegion->contains(
P))
527 if (R == ParentRegion) {
530 for (
unsigned i = 0, e =
Term->getNumSuccessors(); i != e; ++i) {
535 if (Visited.count(
P)) {
537 if (
Term->isConditional()) {
543 Pred[
Other] = {BoolFalse, std::nullopt};
544 Pred[
P] = {BoolTrue, std::nullopt};
548 Pred[
P] = buildCondition(Term, i,
false);
551 LPred[
P] = buildCondition(Term, i,
true);
556 while (
R->getParent() != ParentRegion)
564 if (Visited.count(Entry))
565 Pred[
Entry] = {BoolTrue, std::nullopt};
567 LPred[
Entry] = {BoolFalse, std::nullopt};
573void StructurizeCFG::collectInfos() {
586 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
587 <<
RN->getEntry()->getName() <<
"\n");
590 gatherPredicates(RN);
593 Visited.insert(
RN->getEntry());
609void StructurizeCFG::insertConditions(
bool Loops) {
610 BranchVector &Conds =
Loops ? LoopConds : Conditions;
623 if (Preds.
size() == 1 && Preds.
begin()->first == Parent) {
624 auto &PI = Preds.
begin()->second;
625 Term->setCondition(PI.Pred);
626 CondBranchWeights::setMetadata(*Term, PI.Weights);
631 NearestCommonDominator Dominator(DT);
632 Dominator.addBlock(Parent);
634 for (
auto [BB, PI] : Preds) {
637 Dominator.addAndRememberBlock(BB);
640 if (!Dominator.resultIsRememberedBlock())
649void StructurizeCFG::simplifyConditions() {
651 for (
auto &
I : concat<PredMap::value_type>(Predicates, LoopPreds)) {
652 auto &Preds =
I.second;
653 for (
auto [BB, PI] : Preds) {
656 !PI.Pred->use_empty()) {
657 if (
auto *InvertedCmp = dyn_cast<CmpInst>(Inverted)) {
658 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
660 InstToErase.
push_back(cast<Instruction>(PI.Pred));
665 for (
auto *
I : InstToErase)
666 I->eraseFromParent();
672 PhiMap &
Map = DeletedPhis[To];
674 bool Recorded =
false;
675 while (
Phi.getBasicBlockIndex(
From) != -1) {
679 AffectedPhis.push_back(&Phi);
692 AddedPhis[To].push_back(
From);
699void StructurizeCFG::findUndefBlocks(
728 if (PHIBlock == ParentRegion->getExit()) {
730 if (ParentRegion->contains(
P))
741 while (!
Stack.empty()) {
743 if (!VisitedBlock.
insert(Current).second)
746 if (FlowSet.contains(Current)) {
749 }
else if (!Incomings.
contains(Current)) {
761void StructurizeCFG::mergeIfCompatible(
771 BBValueVector &IncomingA = DeletedPhis[LeaderA->
getParent()][LeaderA];
772 BBValueVector &IncomingB = DeletedPhis[LeaderB->
getParent()][LeaderB];
775 for (
auto [BB, V] : IncomingB) {
776 auto BBIt = Mergeable.find(BB);
777 if (BBIt != Mergeable.end() && BBIt->second != V)
781 Mergeable.insert({BB,
V});
785 IncomingA.assign(Mergeable.begin(), Mergeable.end());
790void StructurizeCFG::setPhiValues() {
817 for (
const auto &[To,
From] : AddedPhis) {
818 auto OldPhiIt = DeletedPhis.find(To);
819 if (OldPhiIt == DeletedPhis.end())
822 PhiMap &BlkPhis = OldPhiIt->second;
827 if (!BlkPhis.empty()) {
828 for (
const auto &VI : BlkPhis.front().second)
830 findUndefBlocks(To, Incomings, UndefBlks);
833 for (
const auto &[Phi, Incomings] : OldPhiIt->second) {
835 for (
const auto &[BB, V] : Incomings) {
838 if (
PHINode *
P = dyn_cast<PHINode>(V))
842 for (
auto *OtherPhi : IncomingPHIs) {
844 if (!DeletedPhis.contains(OtherPhi->getParent()))
846 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
851 for (
const auto &AddedPhi : AddedPhis) {
853 const BBVector &
From = AddedPhi.second;
855 if (!DeletedPhis.count(To))
858 PhiMap &
Map = DeletedPhis[To];
860 for (
const auto &[Phi,
Incoming] : Map) {
862 Updater.Initialize(
Phi->getType(),
"");
863 Updater.AddAvailableValue(&
Func->getEntryBlock(), Undef);
864 Updater.AddAvailableValue(To, Undef);
868 bool UseIncomingOfLeader =
870 const auto &IncomingMap =
871 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
875 for (
const auto &[BB, V] : IncomingMap) {
876 Updater.AddAvailableValue(BB, V);
877 if (isa<Constant>(V))
881 for (
auto UB : UndefBlks) {
890 if (Updater.HasValueForBlock(UB))
893 Updater.AddAvailableValue(UB, Undef);
897 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
898 AffectedPhis.push_back(Phi);
902 AffectedPhis.append(InsertedPhis.
begin(), InsertedPhis.
end());
905void StructurizeCFG::simplifyAffectedPhis() {
913 Q.CanUseUndef =
false;
914 for (
WeakVH VH : AffectedPhis) {
915 if (
auto Phi = dyn_cast_or_null<PHINode>(VH)) {
917 Phi->replaceAllUsesWith(NewValue);
918 Phi->eraseFromParent();
927void StructurizeCFG::killTerminator(
BasicBlock *BB) {
933 delPhiValues(BB, Succ);
935 Term->eraseFromParent();
940 bool IncludeDominator) {
941 if (
Node->isSubRegion()) {
953 delPhiValues(BB, OldExit);
955 addPhiValues(BB, NewExit);
958 if (IncludeDominator) {
977 addPhiValues(BB, NewExit);
978 if (IncludeDominator)
987 Order.back()->getEntry();
990 FlowSet.insert(
Flow);
995 TermDL[
Flow] = std::move(
DL);
998 ParentRegion->getRegionInfo()->setRegionFor(
Flow, ParentRegion);
1003BasicBlock *StructurizeCFG::needPrefix(
bool NeedEmpty) {
1006 if (!PrevNode->isSubRegion()) {
1007 killTerminator(Entry);
1008 if (!NeedEmpty ||
Entry->getFirstInsertionPt() ==
Entry->end())
1016 changeExit(PrevNode,
Flow,
true);
1017 PrevNode = ParentRegion->getBBNode(
Flow);
1023 bool ExitUseAllowed) {
1024 if (!Order.empty() || !ExitUseAllowed)
1025 return getNextFlow(
Flow);
1029 addPhiValues(
Flow, Exit);
1034void StructurizeCFG::setPrevNode(
BasicBlock *BB) {
1035 PrevNode = ParentRegion->contains(BB) ? ParentRegion->getBBNode(BB)
1042 return llvm::all_of(Preds, [&](std::pair<BasicBlock *, PredInfo> Pred) {
1050 bool Dominated =
false;
1056 for (
auto [BB, PI] : Preds) {
1057 if (PI.Pred != BoolTrue)
1060 if (!Dominated && DT->
dominates(BB, PrevNode->getEntry()))
1069void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
1072 Visited.insert(
Node->getEntry());
1074 if (isPredictableTrue(
Node)) {
1077 changeExit(PrevNode,
Node->getEntry(),
true);
1091 Conditions.push_back(Br);
1092 addPhiValues(
Flow, Entry);
1096 while (!Order.empty() && !Visited.count(LoopEnd) &&
1097 dominatesPredicates(Entry, Order.back())) {
1098 handleLoops(
false, LoopEnd);
1101 changeExit(PrevNode, Next,
false);
1106void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
1111 if (!
Loops.count(LoopStart)) {
1112 wireFlow(ExitUseAllowed, LoopEnd);
1116 if (!isPredictableTrue(
Node))
1117 LoopStart = needPrefix(
true);
1120 wireFlow(
false, LoopEnd);
1121 while (!Visited.count(LoopEnd)) {
1122 handleLoops(
false, LoopEnd);
1128 LoopEnd = needPrefix(
false);
1129 BasicBlock *Next = needPostfix(LoopEnd, ExitUseAllowed);
1132 LoopConds.push_back(Br);
1133 addPhiValues(LoopEnd, LoopStart);
1139void StructurizeCFG::createFlow() {
1141 bool EntryDominatesExit = DT->
dominates(ParentRegion->getEntry(), Exit);
1143 AffectedPhis.clear();
1144 DeletedPhis.clear();
1152 while (!Order.empty()) {
1153 handleLoops(EntryDominatesExit,
nullptr);
1157 changeExit(PrevNode, Exit, EntryDominatesExit);
1159 assert(EntryDominatesExit);
1164void StructurizeCFG::rebuildSSA() {
1166 for (
BasicBlock *BB : ParentRegion->blocks())
1168 bool Initialized =
false;
1173 if (
User->getParent() == BB) {
1175 }
else if (
PHINode *UserPN = dyn_cast<PHINode>(
User)) {
1176 if (UserPN->getIncomingBlock(U) == BB)
1198 bool SubRegionsAreUniform =
true;
1200 unsigned ConditionalDirectChildren = 0;
1202 for (
auto *E : R->elements()) {
1203 if (!E->isSubRegion()) {
1204 auto Br = dyn_cast<BranchInst>(E->getEntry()->getTerminator());
1212 ConditionalDirectChildren++;
1215 <<
" has uniform terminator\n");
1227 auto Br = dyn_cast<BranchInst>(BB->getTerminator());
1233 if (!RelaxedUniformRegions)
1236 SubRegionsAreUniform =
false;
1249 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
1252void StructurizeCFG::init(
Region *R) {
1264 if (
R->isTopLevelRegion())
1273 unsigned UniformMDKindID =
1274 R->getEntry()->getContext().getMDKindID(
"structurizecfg.uniform");
1277 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
1286 if (E->isSubRegion())
1289 if (
Instruction *Term = E->getEntry()->getTerminator())
1290 Term->setMetadata(UniformMDKindID, MD);
1300 if (
R->isTopLevelRegion())
1305 Func =
R->getEntry()->getParent();
1313 insertConditions(
false);
1314 insertConditions(
true);
1316 simplifyConditions();
1317 simplifyAffectedPhis();
1323 DeletedPhis.clear();
1337 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1341 Regions.push_back(&R);
1342 for (
const auto &E : R)
1347 : SkipUniformRegions(SkipUniformRegions_) {
1348 if (ForceSkipUniformRegions.getNumOccurrences())
1349 SkipUniformRegions = ForceSkipUniformRegions.getValue();
1355 OS, MapClassName2PassName);
1356 if (SkipUniformRegions)
1357 OS <<
"<skip-uniform-regions>";
1363 bool Changed =
false;
1368 if (SkipUniformRegions)
1371 std::vector<Region *> Regions;
1373 while (!Regions.empty()) {
1374 Region *R = Regions.back();
1377 StructurizeCFG SCFG;
1380 if (SkipUniformRegions && SCFG.makeUniformRegion(R, *UI)) {
1385 Changed |= SCFG.run(R, DT);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
std::optional< std::vector< StOtherPiece > > Other
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file implements a map that provides insertion order iteration.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
static void addRegionIntoQueue(Region &R, std::deque< Region * > &RQ)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
static void addRegionIntoQueue(Region &R, std::vector< Region * > &Regions)
const char FlowBlockName[]
static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, const UniformityInfo &UA)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
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...
Conditional or Unconditional Branch instruction.
bool isConditional() const
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Analysis pass which computes a DominatorTree.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
member_iterator findLeader(iterator I) const
findLeader - Given a value in the set, return a member iterator for the equivalence class it is in.
iterator insert(const ElemTy &Data)
insert - Insert a new value into the union/find set, ignoring the request if the value already exists...
member_iterator member_end() const
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
union - Merge the two equivalence sets for the specified values, inserting them if they do not alread...
const BasicBlock & getEntryBlock() const
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
This is an important class for using LLVM in a threaded context.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
The pass manager to schedule RegionPasses.
void replaceExit(BlockT *BB)
Replace the exit basic block of the region with the new basic block.
block_range blocks()
Returns a range view of the basic blocks in the region.
BlockT * getExit() const
Get the exit BasicBlock of the Region.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
Analysis pass that exposes the RegionInfo for a function.
RegionT * getRegionFor(BlockT *BB) const
Get the smallest region that contains a BasicBlock.
A pass that runs on each Region in a function.
virtual bool runOnRegion(Region *R, RGPassManager &RGM)=0
Run the pass on a specific Region.
Helper class for SSA formation on a set of values defined in multiple blocks.
void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
Value * GetValueInMiddleOfBlock(BasicBlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
void AddAvailableValue(BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
Implements a dense probed hash-table based set with some number of buckets stored inline.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
static IntegerType * getInt1Ty(LLVMContext &C)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
LLVM Value Representation.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
A nullable Value handle that is nullable.
int getNumOccurrences() const
std::pair< iterator, bool > insert(const ValueT &V)
Specialization of filter_iterator_base for forward iteration only.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
CRTP base class for adapting an iterator to a different type.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
OneUse_match< T > m_OneUse(const T &SubPattern)
BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
@ Undef
Value of the register doesn't matter.
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
APInt operator*(APInt a, uint64_t RHS)
bool hasOnlySimpleTerminator(const Function &F)
auto successors(const MachineBasicBlock *BB)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Pass * createStructurizeCFGPass(bool SkipUniformRegions=false)
When SkipUniformRegions is true the structizer will not structurize regions that only contain uniform...
Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
void initializeStructurizeCFGLegacyPassPass(PassRegistry &)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
auto predecessors(const MachineBasicBlock *BB)
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
Value * invertCondition(Value *Condition)
Invert the given true/false value, possibly reusing an existing copy.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
A CRTP mix-in to automatically provide informational APIs needed for passes.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
StructurizeCFGPass(bool SkipUniformRegions=false)