56#define DEBUG_TYPE "structurizecfg"
65using BBValuePair = std::pair<BasicBlock *, Value *>;
80using MaybeCondBranchWeights = std::optional<class CondBranchWeights>;
82class CondBranchWeights {
89 static MaybeCondBranchWeights tryParse(
const CondBrInst &Br) {
94 return CondBranchWeights(
T,
F);
98 const MaybeCondBranchWeights &Weights) {
101 uint32_t Arr[] = {Weights->TrueWeight, Weights->FalseWeight};
105 CondBranchWeights invert()
const {
106 return CondBranchWeights{FalseWeight, TrueWeight};
112 MaybeCondBranchWeights Weights;
123struct SubGraphTraits {
124 using NodeRef = std::pair<RegionNode *, SmallDenseSet<RegionNode *> *>;
129 class WrappedSuccIterator
131 WrappedSuccIterator, BaseSuccIterator,
132 std::iterator_traits<BaseSuccIterator>::iterator_category, NodeRef,
133 std::ptrdiff_t, NodeRef *, NodeRef> {
140 NodeRef
operator*()
const {
return {*
I, Nodes}; }
143 static bool filterAll(
const NodeRef &
N) {
return true; }
144 static bool filterSet(
const NodeRef &
N) {
return N.second->count(
N.first); }
149 static NodeRef getEntryNode(
Region *R) {
153 static NodeRef getEntryNode(NodeRef
N) {
return N; }
156 auto *filter =
N.second ? &filterSet : &filterAll;
178class NearestCommonDominator {
181 bool ResultIsRemembered =
false;
184 void addBlock(
BasicBlock *BB,
bool Remember) {
187 ResultIsRemembered = Remember;
192 if (NewResult != Result)
193 ResultIsRemembered =
false;
195 ResultIsRemembered |= Remember;
200 explicit NearestCommonDominator(
DominatorTree *DomTree) : DT(DomTree) {}
216 bool resultIsRememberedBlock() {
return ResultIsRemembered; }
265class StructurizeCFG {
281 BBPhiMap DeletedPhis;
282 BB2BBVecMap AddedPhis;
285 BranchVector Conditions;
289 BranchVector LoopConds;
291 Val2BBMap HoistedValues;
304 PredInfo buildCondition(
CondBrInst *Term,
unsigned Idx,
bool Invert);
312 void simplifyConditions();
327 void simplifyAffectedPhis();
329 void simplifyHoistedPhis();
334 bool IncludeDominator);
338 std::pair<BasicBlock *, DebugLoc> needPrefix(
bool NeedEmpty);
348 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
350 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
363 bool SkipUniformRegions;
368 explicit StructurizeCFGLegacyPass(
bool SkipUniformRegions_ =
false)
369 :
FunctionPass(ID), SkipUniformRegions(SkipUniformRegions_) {
375 StringRef getPassName()
const override {
return "Structurize control flow"; }
389char StructurizeCFGLegacyPass::ID = 0;
392 "Structurize the CFG",
false,
false)
418 for (
auto &
Op :
I->operands()) {
419 if (auto *OpI = dyn_cast<Instruction>(Op)) {
421 if (!DT->dominates(OpI->getParent(), HoistTo))
442void StructurizeCFG::hoistZeroCostElseBlockPhiValues(
BasicBlock *ElseBB,
448 if (!ElseSucc || !CommonDominator)
458 for (PHINode &Phi : ElseSucc->
phis()) {
459 Value *ElseVal =
Phi.getIncomingValueForBlock(ElseBB);
461 if (!Inst || !isHoistableInstruction(Inst, ElseBB, CommonDominator))
463 Inst->removeFromParent();
464 Inst->insertInto(CommonDominator,
Term->getIterator());
465 HoistedValues[Inst] = CommonDominator;
472void StructurizeCFG::orderNodes() {
473 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion),
474 GraphTraits<Region *>::nodes_end(ParentRegion)));
478 SmallDenseSet<RegionNode *> Nodes;
479 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
483 unsigned I = 0,
E = Order.size();
500 for (
const auto &
N : SCC) {
501 assert(
I <
E &&
"SCC size mismatch!");
502 Order[
I++] =
N.first;
505 assert(
I ==
E &&
"SCC size mismatch!");
508 if (WorkList.
empty())
517 Nodes.
insert(Order.begin() +
I, Order.begin() +
E - 1);
520 EntryNode.first = Order[
E - 1];
521 EntryNode.second = &Nodes;
526void StructurizeCFG::analyzeLoops(RegionNode *
N) {
527 if (
N->isSubRegion()) {
530 if (Visited.count(Exit))
539 if (Visited.count(Succ))
545PredInfo StructurizeCFG::buildCondition(CondBrInst *Term,
unsigned Idx,
548 auto Weights = CondBranchWeights::tryParse(*Term);
549 if (Idx != (
unsigned)Invert) {
552 Weights = Weights->invert();
554 return {
Cond, Weights};
558void StructurizeCFG::gatherPredicates(RegionNode *
N) {
570 if (R == ParentRegion) {
572 if (Visited.count(
P))
573 Pred[
P] = {BoolTrue, std::nullopt};
575 LPred[
P] = {BoolFalse, std::nullopt};
577 bool Idx = CondBr->getSuccessor(0) == BB ? 0 : 1;
578 if (Visited.count(
P)) {
584 hoistZeroCostElseBlockPhiValues(BB,
Other);
585 Pred[
Other] = {BoolFalse, std::nullopt};
586 Pred[
P] = {BoolTrue, std::nullopt};
588 Pred[
P] = buildCondition(CondBr, Idx,
false);
591 LPred[
P] = buildCondition(CondBr, Idx,
true);
596 while (
R->getParent() != ParentRegion)
604 if (Visited.count(Entry))
605 Pred[
Entry] = {BoolTrue, std::nullopt};
607 LPred[
Entry] = {BoolFalse, std::nullopt};
613void StructurizeCFG::collectInfos() {
624 for (RegionNode *RN :
reverse(Order)) {
626 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
627 <<
RN->getEntry()->getName() <<
"\n");
630 gatherPredicates(RN);
633 Visited.insert(
RN->getEntry());
641void StructurizeCFG::insertConditions(
bool Loops, SSAUpdaterBulk &PhiInserter) {
642 BranchVector &Conds =
Loops ? LoopConds : Conditions;
645 for (
auto [Term, Target] : Conds) {
655 NearestCommonDominator Dominator(DT);
656 Dominator.addBlock(Parent);
658 PredInfo ParentInfo{
nullptr, std::nullopt};
659 for (
auto [BB, PI] : Preds) {
665 Dominator.addAndRememberBlock(BB);
668 if (ParentInfo.Pred) {
669 Term->setCondition(ParentInfo.Pred);
670 CondBranchWeights::setMetadata(*Term, ParentInfo.Weights);
672 if (!Dominator.resultIsRememberedBlock())
675 PhiInserter.
AddUse(Variable, &
Term->getOperandUse(0));
681void StructurizeCFG::simplifyConditions() {
682 SmallVector<Instruction *> InstToErase;
684 auto &Preds =
I.second;
685 for (
auto [BB, PI] : Preds) {
688 !PI.Pred->use_empty()) {
690 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
691 PI.Pred->replaceAllUsesWith(InvertedCmp);
697 for (
auto *
I : InstToErase)
698 I->eraseFromParent();
703void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
705 for (PHINode &Phi : To->
phis()) {
706 bool Recorded =
false;
707 while (
Phi.getBasicBlockIndex(From) != -1) {
711 AffectedPhis.push_back(&Phi);
719void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
720 for (PHINode &Phi : To->
phis()) {
722 Phi.addIncoming(Poison, From);
724 AddedPhis[To].push_back(From);
731void StructurizeCFG::findUndefBlocks(
732 BasicBlock *PHIBlock,
const SmallPtrSet<BasicBlock *, 8> &Incomings,
758 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
759 SmallVector<BasicBlock *, 8>
Stack;
760 if (PHIBlock == ParentRegion->
getExit()) {
773 while (!
Stack.empty()) {
775 if (!VisitedBlock.
insert(Current).second)
778 if (FlowSet.contains(Current))
780 else if (!Incomings.
contains(Current))
791void StructurizeCFG::mergeIfCompatible(
792 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *
A, PHINode *
B) {
799 PHINode *LeaderA = *ItA;
800 PHINode *LeaderB = *ItB;
801 BBValueVector &IncomingA = DeletedPhis[LeaderA->
getParent()][LeaderA];
802 BBValueVector &IncomingB = DeletedPhis[LeaderB->
getParent()][LeaderB];
804 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
805 for (
auto [BB, V] : IncomingB) {
806 auto BBIt = Mergeable.find(BB);
807 if (BBIt != Mergeable.end() && BBIt->second != V)
811 Mergeable.insert({BB,
V});
815 IncomingA.assign(Mergeable.begin(), Mergeable.end());
820void StructurizeCFG::setPhiValues() {
822 SSAUpdater Updater(&InsertedPhis);
823 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
846 EquivalenceClasses<PHINode *> PhiClasses;
847 for (
const auto &[To, From] : AddedPhis) {
848 auto OldPhiIt = DeletedPhis.find(To);
849 if (OldPhiIt == DeletedPhis.end())
852 PhiMap &BlkPhis = OldPhiIt->second;
854 SmallPtrSet<BasicBlock *, 8> Incomings;
857 if (!BlkPhis.
empty()) {
859 findUndefBlocks(To, Incomings, UndefBlks);
862 for (
const auto &[Phi, Incomings] : OldPhiIt->second) {
864 for (
const auto &[BB, V] : Incomings) {
871 for (
auto *OtherPhi : IncomingPHIs) {
873 if (!DeletedPhis.contains(OtherPhi->getParent()))
875 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
880 for (
const auto &AddedPhi : AddedPhis) {
882 const BBVector &From = AddedPhi.second;
884 auto It = DeletedPhis.find(To);
885 if (It == DeletedPhis.end())
890 for (
const auto &[Phi, Incoming] : Map) {
892 Updater.Initialize(
Phi->getType(),
"");
894 Updater.AddAvailableValue(To, Poison);
898 bool UseIncomingOfLeader =
900 const auto &IncomingMap =
901 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
905 for (
const auto &[BB, V] : IncomingMap) {
906 Updater.AddAvailableValue(BB, V);
911 for (
auto UB : UndefBlks) {
917 [&](BasicBlock *CP) {
return DT->
dominates(CP, UB); }))
920 if (Updater.HasValueForBlock(UB))
923 Updater.AddAvailableValue(UB, Poison);
926 for (BasicBlock *FI : From)
927 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
928 AffectedPhis.push_back(Phi);
932 AffectedPhis.append(InsertedPhis.
begin(), InsertedPhis.
end());
937void StructurizeCFG::simplifyHoistedPhis() {
938 for (WeakVH VH : AffectedPhis) {
940 if (!Phi ||
Phi->getNumIncomingValues() != 2)
943 for (
int i = 0; i < 2; i++) {
945 auto BBIt = HoistedValues.find(V);
947 if (BBIt == HoistedValues.end())
950 Value *OtherV =
Phi->getIncomingValue(!i);
955 int PoisonValBBIdx = -1;
962 if (PoisonValBBIdx == -1 ||
969 Phi->setIncomingValue(i, OtherV);
974void StructurizeCFG::simplifyAffectedPhis() {
982 Q.CanUseUndef =
false;
983 for (WeakVH VH : AffectedPhis) {
986 Phi->replaceAllUsesWith(NewValue);
987 Phi->eraseFromParent();
996DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1002 delPhiValues(BB, Succ);
1005 Term->eraseFromParent();
1010void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1011 bool IncludeDominator) {
1012 if (
Node->isSubRegion()) {
1024 delPhiValues(BB, OldExit);
1026 addPhiValues(BB, NewExit);
1029 if (IncludeDominator) {
1048 addPhiValues(BB, NewExit);
1049 if (IncludeDominator)
1055BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1058 Order.back()->getEntry();
1061 FlowSet.insert(
Flow);
1069std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(
bool NeedEmpty) {
1074 if (!NeedEmpty ||
Entry->getFirstInsertionPt() ==
Entry->end())
1082 changeExit(PrevNode,
Flow,
true);
1089 bool ExitUseAllowed) {
1090 if (!Order.empty() || !ExitUseAllowed)
1091 return getNextFlow(
Flow);
1095 addPhiValues(
Flow, Exit);
1100void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1106bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1109 Preds, [&](
const auto &Pred) {
return DT->
dominates(BB, Pred.first); });
1113bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1115 bool Dominated =
false;
1121 for (
auto [BB, PI] : Preds) {
1122 if (PI.Pred != BoolTrue)
1134void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
1135 BasicBlock *LoopEnd) {
1136 RegionNode *
Node = Order.pop_back_val();
1137 Visited.insert(
Node->getEntry());
1139 if (isPredictableTrue(Node)) {
1142 changeExit(PrevNode,
Node->getEntry(),
true);
1147 auto [
Flow,
DL] = needPrefix(
false);
1156 Conditions.push_back({Br,
Entry});
1157 addPhiValues(
Flow, Entry);
1161 while (!Order.empty() && !Visited.count(LoopEnd) &&
1162 dominatesPredicates(Entry, Order.back())) {
1163 handleLoops(
false, LoopEnd);
1166 changeExit(PrevNode,
Next,
false);
1171void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
1172 BasicBlock *LoopEnd) {
1173 RegionNode *
Node = Order.back();
1176 if (!
Loops.count(LoopStart)) {
1177 wireFlow(ExitUseAllowed, LoopEnd);
1181 if (!isPredictableTrue(Node))
1182 LoopStart = needPrefix(
true).first;
1185 wireFlow(
false, LoopEnd);
1186 while (!Visited.count(LoopEnd)) {
1187 handleLoops(
false, LoopEnd);
1194 std::tie(LoopEnd,
DL) = needPrefix(
false);
1199 LoopConds.push_back({Br, Header});
1202 if (LoopStart != Header)
1203 Predicates[Header][LoopEnd] = {BoolTrue, std::nullopt};
1205 addPhiValues(LoopEnd, LoopStart);
1211void StructurizeCFG::createFlow() {
1215 AffectedPhis.clear();
1216 DeletedPhis.clear();
1224 while (!Order.empty()) {
1225 handleLoops(EntryDominatesExit,
nullptr);
1229 changeExit(PrevNode, Exit, EntryDominatesExit);
1231 assert(EntryDominatesExit);
1236void StructurizeCFG::rebuildSSA() {
1238 for (BasicBlock *BB : ParentRegion->
blocks())
1239 for (Instruction &
I : *BB) {
1240 bool Initialized =
false;
1245 if (
User->getParent() == BB) {
1248 if (UserPN->getIncomingBlock(U) == BB)
1284 if (E->isSubRegion())
1286 auto *Br = dyn_cast<CondBrInst>(E->getEntry()->getTerminator());
1287 return Br && UA.isDivergentTerminator(Br);
1291void StructurizeCFG::init(Region *R) {
1292 LLVMContext &
Context =
R->getEntry()->getContext();
1300bool StructurizeCFG::makeUniformRegion(Region *R,
const UniformityInfo &UA) {
1301 if (
R->isTopLevelRegion())
1305 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
1311 LLVMContext &Ctx =
R->getEntry()->getContext();
1312 unsigned UniformMDKindID = Ctx.
getMDKindID(
"structurizecfg.uniform");
1314 for (RegionNode *
E :
R->elements()) {
1315 if (
E->isSubRegion())
1318 E->getEntry()->getTerminator()->setMetadata(UniformMDKindID, MD);
1327bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1328 const TargetTransformInfo *
TTI) {
1339 Func =
R->getEntry()->getParent();
1347 SSAUpdaterBulk PhiInserter;
1348 insertConditions(
false, PhiInserter);
1349 insertConditions(
true, PhiInserter);
1353 simplifyHoistedPhis();
1354 simplifyConditions();
1355 simplifyAffectedPhis();
1361 DeletedPhis.clear();
1374 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1378 Regions.push_back(&R);
1379 for (
const auto &
E : R)
1384 : SkipUniformRegions(SkipUniformRegions_) {}
1388 static_cast<PassInfoMixin<StructurizeCFGPass> *
>(
this)->
printPipeline(
1389 OS, MapClassName2PassName);
1390 if (SkipUniformRegions)
1391 OS <<
"<skip-uniform-regions>";
1399 std::vector<Region *> Regions;
1401 while (!Regions.empty()) {
1402 Region *R = Regions.back();
1405 StructurizeCFG SCFG;
1408 if (UI && SCFG.makeUniformRegion(R, *UI)) {
1418bool StructurizeCFGLegacyPass::runOnFunction(
Function &
F) {
1421 if (
valueOr(Opts.structurizecfg_skip_uniform_regions, SkipUniformRegions))
1422 UI = &getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
1423 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1424 RegionInfo &RI = getAnalysis<RegionInfoPass>().getRegionInfo();
1426 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
1437 if (
valueOr(Opts.structurizecfg_skip_uniform_regions, SkipUniformRegions))
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")
static bool runImpl(MachineFunction &MF)
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.
static bool runOnFunction(Function &F, bool PostInlining)
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.
SmallVector< MachineOperand, 4 > Cond
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 void addRegionIntoQueue(Region &R, std::vector< Region * > &Regions)
const char FlowBlockName[]
static bool hasOnlyUniformBranches(Region *R, const UniformityInfo &UA)
Can region R be left unstructurized because all of its own control flow is uniform?
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 bool hasNPredecessors(unsigned N) const
Return true if this block has exactly N predecessors.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
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; assumes that the block is well-formed.
Conditional Branch instruction.
static CondBrInst * Create(Value *Cond, BasicBlock *IfTrue, BasicBlock *IfFalse, 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.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
const ECValue & insert(const ElemTy &Data)
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
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)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
FunctionPass class - This class is used to implement most global optimizations.
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.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI unsigned getMDKindID(StringRef Name) const
getMDKindID - Return a unique non-zero ID for the specified metadata kind.
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'.
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.
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 * getTopLevelRegion() const
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.
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.
LLVM_ABI void RewriteAndOptimizeAllUses(DominatorTree &DT)
Rewrite all uses and simplify the inserted PHI nodes.
LLVM_ABI void RewriteUseAfterInsertions(Use &U)
Rewrite a use like RewriteUse but handling in-block definitions.
LLVM_ABI void Initialize(Type *Ty, StringRef Name)
Reset this object to get ready for a new set of SSA updates with type 'Ty'.
LLVM_ABI 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.
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.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
LLVM Value Representation.
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().
@ 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)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
@ 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
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)
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...
const ScalarOptions & getScalarOptions(const LLVMContext &C)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
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...
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)
constexpr bool valueOr(BoolOrDefault X, bool Default)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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 &)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI StructurizeCFGPass(bool SkipUniformRegions=false)