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;
136struct SubGraphTraits {
137 using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>;
142 class WrappedSuccIterator
144 WrappedSuccIterator, BaseSuccIterator,
145 typename std::iterator_traits<BaseSuccIterator>::iterator_category,
146 NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> {
153 NodeRef
operator*()
const {
return {*
I, Nodes}; }
156 static bool filterAll(
const NodeRef &
N) {
return true; }
157 static bool filterSet(
const NodeRef &
N) {
return N.second->count(
N.first); }
162 static NodeRef getEntryNode(
Region *R) {
166 static NodeRef getEntryNode(NodeRef
N) {
return N; }
169 auto *filter =
N.second ? &filterSet : &filterAll;
191class NearestCommonDominator {
194 bool ResultIsRemembered =
false;
197 void addBlock(
BasicBlock *BB,
bool Remember) {
200 ResultIsRemembered = Remember;
205 if (NewResult != Result)
206 ResultIsRemembered =
false;
208 ResultIsRemembered |= Remember;
213 explicit NearestCommonDominator(
DominatorTree *DomTree) : DT(DomTree) {}
229 bool resultIsRememberedBlock() {
return ResultIsRemembered; }
278class StructurizeCFG {
295 BBPhiMap DeletedPhis;
296 BB2BBVecMap AddedPhis;
299 BranchVector Conditions;
303 BranchVector LoopConds;
305 Val2BBMap HoistedValues;
315 PredInfo buildCondition(
BranchInst *Term,
unsigned Idx,
bool Invert);
321 void insertConditions(
bool Loops);
323 void simplifyConditions();
338 void simplifyAffectedPhis();
340 void simplifyHoistedPhis();
345 bool IncludeDominator);
349 std::pair<BasicBlock *, DebugLoc> needPrefix(
bool NeedEmpty);
359 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
361 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
373class StructurizeCFGLegacyPass :
public RegionPass {
374 bool SkipUniformRegions;
379 explicit StructurizeCFGLegacyPass(
bool SkipUniformRegions_ =
false)
380 :
RegionPass(
ID), SkipUniformRegions(SkipUniformRegions_) {
382 SkipUniformRegions = ForceSkipUniformRegions.
getValue();
389 if (SkipUniformRegions) {
391 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
392 if (SCFG.makeUniformRegion(R, UA))
395 Function *
F = R->getEntry()->getParent();
397 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*
F);
398 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
399 return SCFG.run(R, DT,
TTI);
402 StringRef getPassName()
const override {
return "Structurize control flow"; }
405 if (SkipUniformRegions)
436 for (
auto &
Op :
I->operands()) {
438 if (OpI->getParent() == BB)
446char StructurizeCFGLegacyPass::ID = 0;
449 "Structurize the CFG",
false,
false)
469void StructurizeCFG::hoistZeroCostElseBlockPhiValues(
BasicBlock *ElseBB,
473 BasicBlock *CommonDominator = DT->findNearestCommonDominator(ElseBB, ThenBB);
475 if (!ElseSucc || !CommonDominator)
479 Value *ElseVal = Phi.getIncomingValueForBlock(ElseBB);
480 auto *Inst = dyn_cast<Instruction>(ElseVal);
481 if (!Inst || !isHoistableInstruction(Inst, ElseBB, TTI))
483 Inst->removeFromParent();
484 Inst->insertInto(CommonDominator, Term->getIterator());
485 HoistedValues[Inst] = CommonDominator;
492void StructurizeCFG::orderNodes() {
493 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion),
494 GraphTraits<Region *>::nodes_end(ParentRegion)));
498 SmallDenseSet<RegionNode *> Nodes;
499 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
503 unsigned I = 0,
E = Order.size();
520 for (
const auto &
N : SCC) {
521 assert(
I <
E &&
"SCC size mismatch!");
522 Order[
I++] =
N.first;
525 assert(
I ==
E &&
"SCC size mismatch!");
528 if (WorkList.
empty())
537 Nodes.
insert(Order.begin() +
I, Order.begin() +
E - 1);
540 EntryNode.first = Order[
E - 1];
541 EntryNode.second = &Nodes;
546void StructurizeCFG::analyzeLoops(RegionNode *
N) {
547 if (
N->isSubRegion()) {
550 if (Visited.count(Exit))
558 for (BasicBlock *Succ :
Term->successors())
559 if (Visited.count(Succ))
565PredInfo StructurizeCFG::buildCondition(BranchInst *Term,
unsigned Idx,
567 Value *
Cond = Invert ? BoolFalse : BoolTrue;
568 MaybeCondBranchWeights Weights;
570 if (
Term->isConditional()) {
572 Weights = CondBranchWeights::tryParse(*Term);
574 if (Idx != (
unsigned)Invert) {
577 Weights = Weights->invert();
580 return {
Cond, Weights};
584void StructurizeCFG::gatherPredicates(RegionNode *
N) {
596 if (R == ParentRegion) {
599 for (
unsigned i = 0, e =
Term->getNumSuccessors(); i != e; ++i) {
604 if (Visited.count(
P)) {
606 if (
Term->isConditional()) {
611 hoistZeroCostElseBlockPhiValues(Succ,
Other);
612 Pred[
Other] = {BoolFalse, std::nullopt};
613 Pred[
P] = {BoolTrue, std::nullopt};
617 Pred[
P] = buildCondition(Term, i,
false);
620 LPred[
P] = buildCondition(Term, i,
true);
625 while (
R->getParent() != ParentRegion)
633 if (Visited.count(Entry))
634 Pred[
Entry] = {BoolTrue, std::nullopt};
636 LPred[
Entry] = {BoolFalse, std::nullopt};
642void StructurizeCFG::collectInfos() {
653 for (RegionNode *RN :
reverse(Order)) {
655 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
656 <<
RN->getEntry()->getName() <<
"\n");
659 gatherPredicates(RN);
662 Visited.insert(
RN->getEntry());
670void StructurizeCFG::insertConditions(
bool Loops) {
671 BranchVector &Conds =
Loops ? LoopConds : Conditions;
673 SSAUpdater PhiInserter;
675 for (BranchInst *Term : Conds) {
687 NearestCommonDominator Dominator(DT);
688 Dominator.addBlock(Parent);
690 PredInfo ParentInfo{
nullptr, std::nullopt};
691 for (
auto [BB, PI] : Preds) {
697 Dominator.addAndRememberBlock(BB);
700 if (ParentInfo.Pred) {
701 Term->setCondition(ParentInfo.Pred);
702 CondBranchWeights::setMetadata(*Term, ParentInfo.Weights);
704 if (!Dominator.resultIsRememberedBlock())
713void StructurizeCFG::simplifyConditions() {
716 auto &Preds =
I.second;
717 for (
auto [BB, PI] : Preds) {
720 !PI.Pred->use_empty()) {
722 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
723 PI.Pred->replaceAllUsesWith(InvertedCmp);
729 for (
auto *
I : InstToErase)
730 I->eraseFromParent();
735void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
737 for (PHINode &Phi : To->
phis()) {
738 bool Recorded =
false;
739 while (
Phi.getBasicBlockIndex(From) != -1) {
743 AffectedPhis.push_back(&Phi);
751void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
752 for (PHINode &Phi : To->
phis()) {
756 AddedPhis[To].push_back(From);
763void StructurizeCFG::findUndefBlocks(
764 BasicBlock *PHIBlock,
const SmallPtrSet<BasicBlock *, 8> &Incomings,
790 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
791 SmallVector<BasicBlock *, 8>
Stack;
792 if (PHIBlock == ParentRegion->
getExit()) {
805 while (!
Stack.empty()) {
807 if (!VisitedBlock.
insert(Current).second)
810 if (FlowSet.contains(Current))
812 else if (!Incomings.
contains(Current))
823void StructurizeCFG::mergeIfCompatible(
824 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *
A, PHINode *
B) {
831 PHINode *LeaderA = *ItA;
832 PHINode *LeaderB = *ItB;
833 BBValueVector &IncomingA = DeletedPhis[LeaderA->
getParent()][LeaderA];
834 BBValueVector &IncomingB = DeletedPhis[LeaderB->
getParent()][LeaderB];
836 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
837 for (
auto [BB, V] : IncomingB) {
838 auto BBIt = Mergeable.find(BB);
839 if (BBIt != Mergeable.end() && BBIt->second != V)
843 Mergeable.insert({BB,
V});
847 IncomingA.assign(Mergeable.begin(), Mergeable.end());
852void StructurizeCFG::setPhiValues() {
854 SSAUpdater Updater(&InsertedPhis);
855 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
878 EquivalenceClasses<PHINode *> PhiClasses;
879 for (
const auto &[To, From] : AddedPhis) {
880 auto OldPhiIt = DeletedPhis.find(To);
881 if (OldPhiIt == DeletedPhis.end())
884 PhiMap &BlkPhis = OldPhiIt->second;
886 SmallPtrSet<BasicBlock *, 8> Incomings;
889 if (!BlkPhis.
empty()) {
891 findUndefBlocks(To, Incomings, UndefBlks);
894 for (
const auto &[Phi, Incomings] : OldPhiIt->second) {
896 for (
const auto &[BB, V] : Incomings) {
903 for (
auto *OtherPhi : IncomingPHIs) {
905 if (!DeletedPhis.contains(OtherPhi->getParent()))
907 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
912 for (
const auto &AddedPhi : AddedPhis) {
914 const BBVector &From = AddedPhi.second;
916 auto It = DeletedPhis.find(To);
917 if (It == DeletedPhis.end())
922 for (
const auto &[Phi, Incoming] : Map) {
924 Updater.Initialize(
Phi->getType(),
"");
926 Updater.AddAvailableValue(To,
Poison);
930 bool UseIncomingOfLeader =
932 const auto &IncomingMap =
933 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
937 for (
const auto &[BB, V] : IncomingMap) {
938 Updater.AddAvailableValue(BB, V);
943 for (
auto UB : UndefBlks) {
949 [&](BasicBlock *CP) {
return DT->
dominates(CP, UB); }))
952 if (Updater.HasValueForBlock(UB))
955 Updater.AddAvailableValue(UB,
Poison);
958 for (BasicBlock *FI : From)
959 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
960 AffectedPhis.push_back(Phi);
964 AffectedPhis.append(InsertedPhis.
begin(), InsertedPhis.
end());
969void StructurizeCFG::simplifyHoistedPhis() {
970 for (WeakVH VH : AffectedPhis) {
972 if (!Phi ||
Phi->getNumIncomingValues() != 2)
975 for (
int i = 0; i < 2; i++) {
977 auto BBIt = HoistedValues.find(V);
979 if (BBIt == HoistedValues.end())
982 Value *OtherV =
Phi->getIncomingValue(!i);
987 int PoisonValBBIdx = -1;
994 if (PoisonValBBIdx == -1 ||
1001 Phi->setIncomingValue(i, OtherV);
1006void StructurizeCFG::simplifyAffectedPhis() {
1014 Q.CanUseUndef =
false;
1015 for (WeakVH VH : AffectedPhis) {
1018 Phi->replaceAllUsesWith(NewValue);
1019 Phi->eraseFromParent();
1028DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1034 delPhiValues(BB, Succ);
1037 Term->eraseFromParent();
1042void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1043 bool IncludeDominator) {
1044 if (
Node->isSubRegion()) {
1056 delPhiValues(BB, OldExit);
1058 addPhiValues(BB, NewExit);
1061 if (IncludeDominator) {
1080 addPhiValues(BB, NewExit);
1081 if (IncludeDominator)
1087BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1090 Order.back()->getEntry();
1093 FlowSet.insert(
Flow);
1101std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(
bool NeedEmpty) {
1106 if (!NeedEmpty ||
Entry->getFirstInsertionPt() ==
Entry->end())
1114 changeExit(PrevNode,
Flow,
true);
1121 bool ExitUseAllowed) {
1122 if (!Order.empty() || !ExitUseAllowed)
1123 return getNextFlow(
Flow);
1127 addPhiValues(
Flow, Exit);
1132void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1138bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1140 return llvm::all_of(Preds, [&](std::pair<BasicBlock *, PredInfo> Pred) {
1146bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1148 bool Dominated =
false;
1154 for (
auto [BB, PI] : Preds) {
1155 if (PI.Pred != BoolTrue)
1167void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
1168 BasicBlock *LoopEnd) {
1169 RegionNode *
Node = Order.pop_back_val();
1170 Visited.insert(
Node->getEntry());
1172 if (isPredictableTrue(Node)) {
1175 changeExit(PrevNode,
Node->getEntry(),
true);
1180 auto [
Flow,
DL] = needPrefix(
false);
1189 Conditions.push_back(Br);
1190 addPhiValues(
Flow, Entry);
1194 while (!Order.empty() && !Visited.count(LoopEnd) &&
1195 dominatesPredicates(Entry, Order.back())) {
1196 handleLoops(
false, LoopEnd);
1199 changeExit(PrevNode,
Next,
false);
1204void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
1205 BasicBlock *LoopEnd) {
1206 RegionNode *
Node = Order.back();
1209 if (!
Loops.count(LoopStart)) {
1210 wireFlow(ExitUseAllowed, LoopEnd);
1214 if (!isPredictableTrue(Node))
1215 LoopStart = needPrefix(
true).first;
1218 wireFlow(
false, LoopEnd);
1219 while (!Visited.count(LoopEnd)) {
1220 handleLoops(
false, LoopEnd);
1227 std::tie(LoopEnd,
DL) = needPrefix(
false);
1231 LoopConds.push_back(Br);
1232 addPhiValues(LoopEnd, LoopStart);
1238void StructurizeCFG::createFlow() {
1242 AffectedPhis.clear();
1243 DeletedPhis.clear();
1251 while (!Order.empty()) {
1252 handleLoops(EntryDominatesExit,
nullptr);
1256 changeExit(PrevNode, Exit, EntryDominatesExit);
1258 assert(EntryDominatesExit);
1263void StructurizeCFG::rebuildSSA() {
1265 for (BasicBlock *BB : ParentRegion->
blocks())
1266 for (Instruction &
I : *BB) {
1267 bool Initialized =
false;
1272 if (
User->getParent() == BB) {
1275 if (UserPN->getIncomingBlock(U) == BB)
1297 bool SubRegionsAreUniform =
true;
1299 unsigned ConditionalDirectChildren = 0;
1301 for (
auto *
E : R->elements()) {
1302 if (!
E->isSubRegion()) {
1311 ConditionalDirectChildren++;
1314 <<
" has uniform terminator\n");
1332 if (!RelaxedUniformRegions)
1335 SubRegionsAreUniform =
false;
1348 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
1351void StructurizeCFG::init(Region *R) {
1352 LLVMContext &
Context =
R->getEntry()->getContext();
1362bool StructurizeCFG::makeUniformRegion(Region *R,
UniformityInfo &UA) {
1363 if (
R->isTopLevelRegion())
1372 unsigned UniformMDKindID =
1373 R->getEntry()->getContext().getMDKindID(
"structurizecfg.uniform");
1376 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
1383 MDNode *MD =
MDNode::get(
R->getEntry()->getParent()->getContext(), {});
1384 for (RegionNode *
E :
R->elements()) {
1385 if (
E->isSubRegion())
1388 if (Instruction *Term =
E->getEntry()->getTerminator())
1389 Term->setMetadata(UniformMDKindID, MD);
1398bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1399 const TargetTransformInfo *
TTI) {
1400 if (
R->isTopLevelRegion())
1405 Func =
R->getEntry()->getParent();
1413 insertConditions(
false);
1414 insertConditions(
true);
1416 simplifyHoistedPhis();
1417 simplifyConditions();
1418 simplifyAffectedPhis();
1424 DeletedPhis.clear();
1437 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1441 Regions.push_back(&R);
1442 for (
const auto &
E : R)
1447 : SkipUniformRegions(SkipUniformRegions_) {
1448 if (ForceSkipUniformRegions.getNumOccurrences())
1449 SkipUniformRegions = ForceSkipUniformRegions.getValue();
1455 OS, MapClassName2PassName);
1456 if (SkipUniformRegions)
1457 OS <<
"<skip-uniform-regions>";
1468 if (SkipUniformRegions)
1471 std::vector<Region *> Regions;
1473 while (!Regions.empty()) {
1474 Region *R = Regions.back();
1477 StructurizeCFG SCFG;
1480 if (SkipUniformRegions && SCFG.makeUniformRegion(R, *UI)) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DenseMap< BasicBlock *, Instruction * > BBPredicates
This file defines the DenseMap class.
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 ...
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
SmallDenseMap< const PHINode *, PhiInfo, 16 > PhiMap
static bool isHoistableInstruction(Instruction *I, BasicBlock *BB, const TargetTransformInfo *TTI)
Checks whether an instruction is zero cost instruction and checks if the operands are from different ...
const char FlowBlockName[]
static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, const UniformityInfo &UA)
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.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
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 LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI 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...
const ECValue & 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 findLeader(const ElemTy &V) const
findLeader - Given a value in the set, return a member iterator for the equivalence class it is in.
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 DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
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.
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.
void setIncomingValue(unsigned i, Value *V)
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI 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...
static LLVM_ABI 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.
PreservedAnalyses & 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.
RegionNodeT * getBBNode(BlockT *BB) const
Get the BasicBlock RegionNode for a BasicBlock.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
RegionInfoT * getRegionInfo() const
Return the RegionInfo object, that belongs to this Region.
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
Analysis pass that exposes the RegionInfo for a function.
RegionT * getRegionFor(BlockT *BB) const
Get the smallest region that contains a BasicBlock.
bool isSubRegion() const
Is this RegionNode a subregion?
BlockT * getEntry() const
Get the entry BasicBlock of this RegionNode.
A pass that runs on each Region in a function.
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.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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.
Analysis pass providing the TargetTransformInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
LLVM Value Representation.
int getNumOccurrences() const
std::pair< iterator, bool > insert(const ValueT &V)
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.
static scc_iterator begin(const GraphT &G)
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.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< SSAContext > UniformityInfo
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
APInt operator*(APInt a, uint64_t RHS)
LLVM_ABI bool hasOnlySimpleTerminator(const Function &F)
auto successors(const MachineBasicBlock *BB)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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...
LLVM_ABI Pass * createStructurizeCFGPass(bool SkipUniformRegions=false)
When SkipUniformRegions is true the structizer will not structurize regions that only contain uniform...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
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)
LLVM_ABI 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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
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...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
FunctionAddr VTableAddr Next
DWARFExpression::Operation Op
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI Value * invertCondition(Value *Condition)
Invert the given true/false value, possibly reusing an existing copy.
filter_iterator_impl< WrappedIteratorT, PredicateT, detail::fwd_or_bidi_tag< WrappedIteratorT > > filter_iterator
Defines filter_iterator to a suitable specialization of filter_iterator_impl, based on the underlying...
LLVM_ABI void initializeStructurizeCFGLegacyPassPass(PassRegistry &)
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)