57#define DEBUG_TYPE "structurizecfg"
65 "structurizecfg-skip-uniform-regions",
67 cl::desc(
"Force whether the StructurizeCFG pass skips uniform regions"),
71 RelaxedUniformRegions(
"structurizecfg-relaxed-uniform-regions",
cl::Hidden,
72 cl::desc(
"Allow relaxed uniform region checks"),
77using BBValuePair = std::pair<BasicBlock *, Value *>;
91using MaybeCondBranchWeights = std::optional<class CondBranchWeights>;
93class CondBranchWeights {
100 static MaybeCondBranchWeights tryParse(
const BranchInst &Br) {
107 return CondBranchWeights(
T,
F);
111 const MaybeCondBranchWeights &Weights) {
115 uint32_t Arr[] = {Weights->TrueWeight, Weights->FalseWeight};
119 CondBranchWeights invert()
const {
120 return CondBranchWeights{FalseWeight, TrueWeight};
126 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); }
163 static NodeRef getEntryNode(
Region *R) {
167 static NodeRef getEntryNode(NodeRef
N) {
return N; }
170 auto *filter =
N.second ? &filterSet : &filterAll;
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 Val2BBMap HoistedValues;
319 PredInfo buildCondition(
BranchInst *Term,
unsigned Idx,
bool Invert);
327 void simplifyConditions();
342 void simplifyAffectedPhis();
344 void simplifyHoistedPhis();
349 bool IncludeDominator);
353 std::pair<BasicBlock *, DebugLoc> needPrefix(
bool NeedEmpty);
363 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
365 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
377class StructurizeCFGLegacyPass :
public RegionPass {
378 bool SkipUniformRegions;
383 explicit StructurizeCFGLegacyPass(
bool SkipUniformRegions_ =
false)
384 :
RegionPass(
ID), SkipUniformRegions(SkipUniformRegions_) {
386 SkipUniformRegions = ForceSkipUniformRegions.
getValue();
393 if (SkipUniformRegions) {
395 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
396 if (SCFG.makeUniformRegion(R, UA))
399 Function *
F = R->getEntry()->getParent();
401 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*
F);
402 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
403 return SCFG.run(R, DT,
TTI);
406 StringRef getPassName()
const override {
return "Structurize control flow"; }
409 if (SkipUniformRegions)
422char StructurizeCFGLegacyPass::ID = 0;
425 "Structurize the CFG",
false,
false)
450 for (
auto &
Op :
I->operands()) {
451 if (auto *OpI = dyn_cast<Instruction>(Op)) {
453 if (!DT->dominates(OpI->getParent(), HoistTo))
474void StructurizeCFG::hoistZeroCostElseBlockPhiValues(
BasicBlock *ElseBB,
480 if (!ElseSucc || !CommonDominator)
483 for (PHINode &Phi : ElseSucc->
phis()) {
484 Value *ElseVal =
Phi.getIncomingValueForBlock(ElseBB);
486 if (!Inst || !isHoistableInstruction(Inst, ElseBB, CommonDominator))
488 Inst->removeFromParent();
489 Inst->insertInto(CommonDominator,
Term->getIterator());
490 HoistedValues[Inst] = CommonDominator;
497void StructurizeCFG::orderNodes() {
498 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion),
499 GraphTraits<Region *>::nodes_end(ParentRegion)));
503 SmallDenseSet<RegionNode *> Nodes;
504 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
508 unsigned I = 0,
E = Order.size();
525 for (
const auto &
N : SCC) {
526 assert(
I <
E &&
"SCC size mismatch!");
527 Order[
I++] =
N.first;
530 assert(
I ==
E &&
"SCC size mismatch!");
533 if (WorkList.
empty())
542 Nodes.
insert(Order.begin() +
I, Order.begin() +
E - 1);
545 EntryNode.first = Order[
E - 1];
546 EntryNode.second = &Nodes;
551void StructurizeCFG::analyzeLoops(RegionNode *
N) {
552 if (
N->isSubRegion()) {
555 if (Visited.count(Exit))
563 for (BasicBlock *Succ :
Term->successors())
564 if (Visited.count(Succ))
570PredInfo StructurizeCFG::buildCondition(BranchInst *Term,
unsigned Idx,
572 Value *
Cond = Invert ? BoolFalse : BoolTrue;
573 MaybeCondBranchWeights Weights;
575 if (
Term->isConditional()) {
577 Weights = CondBranchWeights::tryParse(*Term);
579 if (Idx != (
unsigned)Invert) {
582 Weights = Weights->invert();
585 return {
Cond, Weights};
589void StructurizeCFG::gatherPredicates(RegionNode *
N) {
601 if (R == ParentRegion) {
604 for (
unsigned i = 0, e =
Term->getNumSuccessors(); i != e; ++i) {
609 if (Visited.count(
P)) {
611 if (
Term->isConditional()) {
616 hoistZeroCostElseBlockPhiValues(Succ,
Other);
617 Pred[
Other] = {BoolFalse, std::nullopt};
618 Pred[
P] = {BoolTrue, std::nullopt};
622 Pred[
P] = buildCondition(Term, i,
false);
625 LPred[
P] = buildCondition(Term, i,
true);
630 while (
R->getParent() != ParentRegion)
638 if (Visited.count(Entry))
639 Pred[
Entry] = {BoolTrue, std::nullopt};
641 LPred[
Entry] = {BoolFalse, std::nullopt};
647void StructurizeCFG::collectInfos() {
658 for (RegionNode *RN :
reverse(Order)) {
660 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
661 <<
RN->getEntry()->getName() <<
"\n");
664 gatherPredicates(RN);
667 Visited.insert(
RN->getEntry());
675void StructurizeCFG::insertConditions(
bool Loops, SSAUpdaterBulk &PhiInserter) {
676 BranchVector &Conds =
Loops ? LoopConds : Conditions;
679 for (BranchInst *Term : Conds) {
692 NearestCommonDominator Dominator(DT);
693 Dominator.addBlock(Parent);
695 PredInfo ParentInfo{
nullptr, std::nullopt};
696 for (
auto [BB, PI] : Preds) {
702 Dominator.addAndRememberBlock(BB);
705 if (ParentInfo.Pred) {
706 Term->setCondition(ParentInfo.Pred);
707 CondBranchWeights::setMetadata(*Term, ParentInfo.Weights);
709 if (!Dominator.resultIsRememberedBlock())
712 PhiInserter.
AddUse(Variable, &
Term->getOperandUse(0));
718void StructurizeCFG::simplifyConditions() {
721 auto &Preds =
I.second;
722 for (
auto [BB, PI] : Preds) {
725 !PI.Pred->use_empty()) {
727 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
728 PI.Pred->replaceAllUsesWith(InvertedCmp);
734 for (
auto *
I : InstToErase)
735 I->eraseFromParent();
740void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
742 for (PHINode &Phi : To->
phis()) {
743 bool Recorded =
false;
744 while (
Phi.getBasicBlockIndex(From) != -1) {
748 AffectedPhis.push_back(&Phi);
756void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
757 for (PHINode &Phi : To->
phis()) {
761 AddedPhis[To].push_back(From);
768void StructurizeCFG::findUndefBlocks(
769 BasicBlock *PHIBlock,
const SmallPtrSet<BasicBlock *, 8> &Incomings,
795 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
796 SmallVector<BasicBlock *, 8>
Stack;
797 if (PHIBlock == ParentRegion->
getExit()) {
810 while (!
Stack.empty()) {
812 if (!VisitedBlock.
insert(Current).second)
815 if (FlowSet.contains(Current))
817 else if (!Incomings.
contains(Current))
828void StructurizeCFG::mergeIfCompatible(
829 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *
A, PHINode *
B) {
836 PHINode *LeaderA = *ItA;
837 PHINode *LeaderB = *ItB;
838 BBValueVector &IncomingA = DeletedPhis[LeaderA->
getParent()][LeaderA];
839 BBValueVector &IncomingB = DeletedPhis[LeaderB->
getParent()][LeaderB];
841 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
842 for (
auto [BB, V] : IncomingB) {
843 auto BBIt = Mergeable.find(BB);
844 if (BBIt != Mergeable.end() && BBIt->second != V)
848 Mergeable.insert({BB,
V});
852 IncomingA.assign(Mergeable.begin(), Mergeable.end());
857void StructurizeCFG::setPhiValues() {
859 SSAUpdater Updater(&InsertedPhis);
860 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
883 EquivalenceClasses<PHINode *> PhiClasses;
884 for (
const auto &[To, From] : AddedPhis) {
885 auto OldPhiIt = DeletedPhis.find(To);
886 if (OldPhiIt == DeletedPhis.end())
889 PhiMap &BlkPhis = OldPhiIt->second;
891 SmallPtrSet<BasicBlock *, 8> Incomings;
894 if (!BlkPhis.
empty()) {
896 findUndefBlocks(To, Incomings, UndefBlks);
899 for (
const auto &[Phi, Incomings] : OldPhiIt->second) {
901 for (
const auto &[BB, V] : Incomings) {
908 for (
auto *OtherPhi : IncomingPHIs) {
910 if (!DeletedPhis.contains(OtherPhi->getParent()))
912 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
917 for (
const auto &AddedPhi : AddedPhis) {
919 const BBVector &From = AddedPhi.second;
921 auto It = DeletedPhis.find(To);
922 if (It == DeletedPhis.end())
927 for (
const auto &[Phi, Incoming] : Map) {
929 Updater.Initialize(
Phi->getType(),
"");
931 Updater.AddAvailableValue(To,
Poison);
935 bool UseIncomingOfLeader =
937 const auto &IncomingMap =
938 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
942 for (
const auto &[BB, V] : IncomingMap) {
943 Updater.AddAvailableValue(BB, V);
948 for (
auto UB : UndefBlks) {
954 [&](BasicBlock *CP) {
return DT->
dominates(CP, UB); }))
957 if (Updater.HasValueForBlock(UB))
960 Updater.AddAvailableValue(UB,
Poison);
963 for (BasicBlock *FI : From)
964 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
965 AffectedPhis.push_back(Phi);
969 AffectedPhis.append(InsertedPhis.
begin(), InsertedPhis.
end());
974void StructurizeCFG::simplifyHoistedPhis() {
975 for (WeakVH VH : AffectedPhis) {
977 if (!Phi ||
Phi->getNumIncomingValues() != 2)
980 for (
int i = 0; i < 2; i++) {
982 auto BBIt = HoistedValues.find(V);
984 if (BBIt == HoistedValues.end())
987 Value *OtherV =
Phi->getIncomingValue(!i);
992 int PoisonValBBIdx = -1;
999 if (PoisonValBBIdx == -1 ||
1006 Phi->setIncomingValue(i, OtherV);
1011void StructurizeCFG::simplifyAffectedPhis() {
1019 Q.CanUseUndef =
false;
1020 for (WeakVH VH : AffectedPhis) {
1023 Phi->replaceAllUsesWith(NewValue);
1024 Phi->eraseFromParent();
1033DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1039 delPhiValues(BB, Succ);
1042 Term->eraseFromParent();
1047void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1048 bool IncludeDominator) {
1049 if (
Node->isSubRegion()) {
1061 delPhiValues(BB, OldExit);
1063 addPhiValues(BB, NewExit);
1066 if (IncludeDominator) {
1085 addPhiValues(BB, NewExit);
1086 if (IncludeDominator)
1092BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1095 Order.back()->getEntry();
1098 FlowSet.insert(
Flow);
1106std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(
bool NeedEmpty) {
1111 if (!NeedEmpty ||
Entry->getFirstInsertionPt() ==
Entry->end())
1119 changeExit(PrevNode,
Flow,
true);
1126 bool ExitUseAllowed) {
1127 if (!Order.empty() || !ExitUseAllowed)
1128 return getNextFlow(
Flow);
1132 addPhiValues(
Flow, Exit);
1137void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1143bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1145 return llvm::all_of(Preds, [&](std::pair<BasicBlock *, PredInfo> Pred) {
1151bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1153 bool Dominated =
false;
1159 for (
auto [BB, PI] : Preds) {
1160 if (PI.Pred != BoolTrue)
1172void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
1173 BasicBlock *LoopEnd) {
1174 RegionNode *
Node = Order.pop_back_val();
1175 Visited.insert(
Node->getEntry());
1177 if (isPredictableTrue(Node)) {
1180 changeExit(PrevNode,
Node->getEntry(),
true);
1185 auto [
Flow,
DL] = needPrefix(
false);
1194 Conditions.push_back(Br);
1195 addPhiValues(
Flow, Entry);
1199 while (!Order.empty() && !Visited.count(LoopEnd) &&
1200 dominatesPredicates(Entry, Order.back())) {
1201 handleLoops(
false, LoopEnd);
1204 changeExit(PrevNode,
Next,
false);
1209void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
1210 BasicBlock *LoopEnd) {
1211 RegionNode *
Node = Order.back();
1214 if (!
Loops.count(LoopStart)) {
1215 wireFlow(ExitUseAllowed, LoopEnd);
1219 if (!isPredictableTrue(Node))
1220 LoopStart = needPrefix(
true).first;
1223 wireFlow(
false, LoopEnd);
1224 while (!Visited.count(LoopEnd)) {
1225 handleLoops(
false, LoopEnd);
1232 std::tie(LoopEnd,
DL) = needPrefix(
false);
1236 LoopConds.push_back(Br);
1237 addPhiValues(LoopEnd, LoopStart);
1243void StructurizeCFG::createFlow() {
1247 AffectedPhis.clear();
1248 DeletedPhis.clear();
1256 while (!Order.empty()) {
1257 handleLoops(EntryDominatesExit,
nullptr);
1261 changeExit(PrevNode, Exit, EntryDominatesExit);
1263 assert(EntryDominatesExit);
1268void StructurizeCFG::rebuildSSA() {
1270 for (BasicBlock *BB : ParentRegion->
blocks())
1271 for (Instruction &
I : *BB) {
1272 bool Initialized =
false;
1277 if (
User->getParent() == BB) {
1280 if (UserPN->getIncomingBlock(U) == BB)
1302 bool SubRegionsAreUniform =
true;
1304 unsigned ConditionalDirectChildren = 0;
1306 for (
auto *
E : R->elements()) {
1307 if (!
E->isSubRegion()) {
1316 ConditionalDirectChildren++;
1319 <<
" has uniform terminator\n");
1337 if (!RelaxedUniformRegions)
1340 SubRegionsAreUniform =
false;
1353 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
1356void StructurizeCFG::init(Region *R) {
1357 LLVMContext &
Context =
R->getEntry()->getContext();
1367bool StructurizeCFG::makeUniformRegion(Region *R,
UniformityInfo &UA) {
1368 if (
R->isTopLevelRegion())
1377 unsigned UniformMDKindID =
1378 R->getEntry()->getContext().getMDKindID(
"structurizecfg.uniform");
1381 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
1388 MDNode *MD =
MDNode::get(
R->getEntry()->getParent()->getContext(), {});
1389 for (RegionNode *
E :
R->elements()) {
1390 if (
E->isSubRegion())
1393 if (Instruction *Term =
E->getEntry()->getTerminator())
1394 Term->setMetadata(UniformMDKindID, MD);
1403bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1404 const TargetTransformInfo *
TTI) {
1405 if (
R->isTopLevelRegion())
1410 Func =
R->getEntry()->getParent();
1419 SSAUpdaterBulk PhiInserter;
1420 insertConditions(
false, PhiInserter);
1421 insertConditions(
true, PhiInserter);
1425 simplifyHoistedPhis();
1426 simplifyConditions();
1427 simplifyAffectedPhis();
1433 DeletedPhis.clear();
1446 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1450 Regions.push_back(&R);
1451 for (
const auto &
E : R)
1456 : SkipUniformRegions(SkipUniformRegions_) {
1457 if (ForceSkipUniformRegions.getNumOccurrences())
1458 SkipUniformRegions = ForceSkipUniformRegions.getValue();
1464 OS, MapClassName2PassName);
1465 if (SkipUniformRegions)
1466 OS <<
"<skip-uniform-regions>";
1477 if (SkipUniformRegions)
1480 std::vector<Region *> Regions;
1482 while (!Regions.empty()) {
1483 Region *R = Regions.back();
1486 StructurizeCFG SCFG;
1489 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
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.
Helper class for SSA formation on a set of values defined in multiple blocks.
LLVM_ABI unsigned AddVariable(StringRef Name, Type *Ty)
Add a new variable to the SSA rewriter.
LLVM_ABI void AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V)
Indicate that a rewritten value is available in the specified block with the specified value.
LLVM_ABI void AddUse(unsigned Var, Use *U)
Record a use of the symbolic value.
void RewriteAndOptimizeAllUses(DominatorTree &DT)
Rewrite all uses and simplify the inserted PHI nodes.
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'.
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.
LLVM_ABI void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected, bool ElideAllZero=false)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
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 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)