57#define DEBUG_TYPE "structurizecfg"
66using 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 {
282 BBPhiMap DeletedPhis;
283 BB2BBVecMap AddedPhis;
286 BranchVector Conditions;
290 BranchVector LoopConds;
292 Val2BBMap HoistedValues;
305 PredInfo buildCondition(
CondBrInst *Term,
unsigned Idx,
bool Invert);
313 void simplifyConditions();
328 void simplifyAffectedPhis();
330 void simplifyHoistedPhis();
335 bool IncludeDominator);
339 std::pair<BasicBlock *, DebugLoc> needPrefix(
bool NeedEmpty);
349 void wireFlow(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
351 void handleLoops(
bool ExitUseAllowed,
BasicBlock *LoopEnd);
363class StructurizeCFGLegacyPass :
public RegionPass {
364 bool SkipUniformRegions;
369 explicit StructurizeCFGLegacyPass(
bool SkipUniformRegions_ =
false)
370 :
RegionPass(ID), SkipUniformRegions(SkipUniformRegions_) {
372 valueOr(ScalarOptions::Global.structurizecfg_skip_uniform_regions,
380 if (SkipUniformRegions) {
382 getAnalysis<UniformityInfoWrapperPass>().getUniformityInfo();
383 if (SCFG.makeUniformRegion(R, UA))
386 Function *
F = R->getEntry()->getParent();
388 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*
F);
389 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
390 return SCFG.run(R, DT,
TTI);
393 StringRef getPassName()
const override {
return "Structurize control flow"; }
396 if (SkipUniformRegions)
409char StructurizeCFGLegacyPass::ID = 0;
412 "Structurize the CFG",
false,
false)
437 for (
auto &
Op :
I->operands()) {
438 if (auto *OpI = dyn_cast<Instruction>(Op)) {
440 if (!DT->dominates(OpI->getParent(), HoistTo))
461void StructurizeCFG::hoistZeroCostElseBlockPhiValues(
BasicBlock *ElseBB,
467 if (!ElseSucc || !CommonDominator)
477 for (PHINode &Phi : ElseSucc->
phis()) {
478 Value *ElseVal =
Phi.getIncomingValueForBlock(ElseBB);
480 if (!Inst || !isHoistableInstruction(Inst, ElseBB, CommonDominator))
482 Inst->removeFromParent();
483 Inst->insertInto(CommonDominator,
Term->getIterator());
484 HoistedValues[Inst] = CommonDominator;
491void StructurizeCFG::orderNodes() {
492 Order.resize(std::distance(GraphTraits<Region *>::nodes_begin(ParentRegion),
493 GraphTraits<Region *>::nodes_end(ParentRegion)));
497 SmallDenseSet<RegionNode *> Nodes;
498 auto EntryNode = SubGraphTraits::getEntryNode(ParentRegion);
502 unsigned I = 0,
E = Order.size();
519 for (
const auto &
N : SCC) {
520 assert(
I <
E &&
"SCC size mismatch!");
521 Order[
I++] =
N.first;
524 assert(
I ==
E &&
"SCC size mismatch!");
527 if (WorkList.
empty())
536 Nodes.
insert(Order.begin() +
I, Order.begin() +
E - 1);
539 EntryNode.first = Order[
E - 1];
540 EntryNode.second = &Nodes;
545void StructurizeCFG::analyzeLoops(RegionNode *
N) {
546 if (
N->isSubRegion()) {
549 if (Visited.count(Exit))
558 if (Visited.count(Succ))
564PredInfo StructurizeCFG::buildCondition(CondBrInst *Term,
unsigned Idx,
567 auto Weights = CondBranchWeights::tryParse(*Term);
568 if (Idx != (
unsigned)Invert) {
571 Weights = Weights->invert();
573 return {
Cond, Weights};
577void StructurizeCFG::gatherPredicates(RegionNode *
N) {
589 if (R == ParentRegion) {
591 if (Visited.count(
P))
592 Pred[
P] = {BoolTrue, std::nullopt};
594 LPred[
P] = {BoolFalse, std::nullopt};
596 bool Idx = CondBr->getSuccessor(0) == BB ? 0 : 1;
597 if (Visited.count(
P)) {
603 hoistZeroCostElseBlockPhiValues(BB,
Other);
604 Pred[
Other] = {BoolFalse, std::nullopt};
605 Pred[
P] = {BoolTrue, std::nullopt};
607 Pred[
P] = buildCondition(CondBr, Idx,
false);
610 LPred[
P] = buildCondition(CondBr, Idx,
true);
615 while (
R->getParent() != ParentRegion)
623 if (Visited.count(Entry))
624 Pred[
Entry] = {BoolTrue, std::nullopt};
626 LPred[
Entry] = {BoolFalse, std::nullopt};
632void StructurizeCFG::collectInfos() {
643 for (RegionNode *RN :
reverse(Order)) {
645 << (
RN->isSubRegion() ?
"SubRegion with entry: " :
"")
646 <<
RN->getEntry()->getName() <<
"\n");
649 gatherPredicates(RN);
652 Visited.insert(
RN->getEntry());
660void StructurizeCFG::insertConditions(
bool Loops, SSAUpdaterBulk &PhiInserter) {
661 BranchVector &Conds =
Loops ? LoopConds : Conditions;
664 for (CondBrInst *Term : Conds) {
675 NearestCommonDominator Dominator(DT);
676 Dominator.addBlock(Parent);
678 PredInfo ParentInfo{
nullptr, std::nullopt};
679 for (
auto [BB, PI] : Preds) {
685 Dominator.addAndRememberBlock(BB);
688 if (ParentInfo.Pred) {
689 Term->setCondition(ParentInfo.Pred);
690 CondBranchWeights::setMetadata(*Term, ParentInfo.Weights);
692 if (!Dominator.resultIsRememberedBlock())
695 PhiInserter.
AddUse(Variable, &
Term->getOperandUse(0));
701void StructurizeCFG::simplifyConditions() {
702 SmallVector<Instruction *> InstToErase;
704 auto &Preds =
I.second;
705 for (
auto [BB, PI] : Preds) {
708 !PI.Pred->use_empty()) {
710 InvertedCmp->setPredicate(InvertedCmp->getInversePredicate());
711 PI.Pred->replaceAllUsesWith(InvertedCmp);
717 for (
auto *
I : InstToErase)
718 I->eraseFromParent();
723void StructurizeCFG::delPhiValues(BasicBlock *From, BasicBlock *To) {
725 for (PHINode &Phi : To->
phis()) {
726 bool Recorded =
false;
727 while (
Phi.getBasicBlockIndex(From) != -1) {
731 AffectedPhis.push_back(&Phi);
739void StructurizeCFG::addPhiValues(BasicBlock *From, BasicBlock *To) {
740 for (PHINode &Phi : To->
phis()) {
742 Phi.addIncoming(Poison, From);
744 AddedPhis[To].push_back(From);
751void StructurizeCFG::findUndefBlocks(
752 BasicBlock *PHIBlock,
const SmallPtrSet<BasicBlock *, 8> &Incomings,
778 SmallPtrSet<BasicBlock *, 8> VisitedBlock;
779 SmallVector<BasicBlock *, 8>
Stack;
780 if (PHIBlock == ParentRegion->
getExit()) {
793 while (!
Stack.empty()) {
795 if (!VisitedBlock.
insert(Current).second)
798 if (FlowSet.contains(Current))
800 else if (!Incomings.
contains(Current))
811void StructurizeCFG::mergeIfCompatible(
812 EquivalenceClasses<PHINode *> &PhiClasses, PHINode *
A, PHINode *
B) {
819 PHINode *LeaderA = *ItA;
820 PHINode *LeaderB = *ItB;
821 BBValueVector &IncomingA = DeletedPhis[LeaderA->
getParent()][LeaderA];
822 BBValueVector &IncomingB = DeletedPhis[LeaderB->
getParent()][LeaderB];
824 DenseMap<BasicBlock *, Value *> Mergeable(IncomingA.begin(), IncomingA.end());
825 for (
auto [BB, V] : IncomingB) {
826 auto BBIt = Mergeable.find(BB);
827 if (BBIt != Mergeable.end() && BBIt->second != V)
831 Mergeable.insert({BB,
V});
835 IncomingA.assign(Mergeable.begin(), Mergeable.end());
840void StructurizeCFG::setPhiValues() {
842 SSAUpdater Updater(&InsertedPhis);
843 DenseMap<BasicBlock *, SmallVector<BasicBlock *>> UndefBlksMap;
866 EquivalenceClasses<PHINode *> PhiClasses;
867 for (
const auto &[To, From] : AddedPhis) {
868 auto OldPhiIt = DeletedPhis.find(To);
869 if (OldPhiIt == DeletedPhis.end())
872 PhiMap &BlkPhis = OldPhiIt->second;
874 SmallPtrSet<BasicBlock *, 8> Incomings;
877 if (!BlkPhis.
empty()) {
879 findUndefBlocks(To, Incomings, UndefBlks);
882 for (
const auto &[Phi, Incomings] : OldPhiIt->second) {
884 for (
const auto &[BB, V] : Incomings) {
891 for (
auto *OtherPhi : IncomingPHIs) {
893 if (!DeletedPhis.contains(OtherPhi->getParent()))
895 mergeIfCompatible(PhiClasses, Phi, OtherPhi);
900 for (
const auto &AddedPhi : AddedPhis) {
902 const BBVector &From = AddedPhi.second;
904 auto It = DeletedPhis.find(To);
905 if (It == DeletedPhis.end())
910 for (
const auto &[Phi, Incoming] : Map) {
912 Updater.Initialize(
Phi->getType(),
"");
914 Updater.AddAvailableValue(To, Poison);
918 bool UseIncomingOfLeader =
920 const auto &IncomingMap =
921 UseIncomingOfLeader ? DeletedPhis[(*LeaderIt)->getParent()][*LeaderIt]
925 for (
const auto &[BB, V] : IncomingMap) {
926 Updater.AddAvailableValue(BB, V);
931 for (
auto UB : UndefBlks) {
937 [&](BasicBlock *CP) {
return DT->
dominates(CP, UB); }))
940 if (Updater.HasValueForBlock(UB))
943 Updater.AddAvailableValue(UB, Poison);
946 for (BasicBlock *FI : From)
947 Phi->setIncomingValueForBlock(FI, Updater.GetValueAtEndOfBlock(FI));
948 AffectedPhis.push_back(Phi);
952 AffectedPhis.append(InsertedPhis.
begin(), InsertedPhis.
end());
957void StructurizeCFG::simplifyHoistedPhis() {
958 for (WeakVH VH : AffectedPhis) {
960 if (!Phi ||
Phi->getNumIncomingValues() != 2)
963 for (
int i = 0; i < 2; i++) {
965 auto BBIt = HoistedValues.find(V);
967 if (BBIt == HoistedValues.end())
970 Value *OtherV =
Phi->getIncomingValue(!i);
975 int PoisonValBBIdx = -1;
982 if (PoisonValBBIdx == -1 ||
989 Phi->setIncomingValue(i, OtherV);
994void StructurizeCFG::simplifyAffectedPhis() {
1002 Q.CanUseUndef =
false;
1003 for (WeakVH VH : AffectedPhis) {
1006 Phi->replaceAllUsesWith(NewValue);
1007 Phi->eraseFromParent();
1016DebugLoc StructurizeCFG::killTerminator(BasicBlock *BB) {
1022 delPhiValues(BB, Succ);
1025 Term->eraseFromParent();
1030void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
1031 bool IncludeDominator) {
1032 if (
Node->isSubRegion()) {
1044 delPhiValues(BB, OldExit);
1046 addPhiValues(BB, NewExit);
1049 if (IncludeDominator) {
1068 addPhiValues(BB, NewExit);
1069 if (IncludeDominator)
1075BasicBlock *StructurizeCFG::getNextFlow(BasicBlock *Dominator) {
1078 Order.back()->getEntry();
1081 FlowSet.insert(
Flow);
1089std::pair<BasicBlock *, DebugLoc> StructurizeCFG::needPrefix(
bool NeedEmpty) {
1094 if (!NeedEmpty ||
Entry->getFirstInsertionPt() ==
Entry->end())
1102 changeExit(PrevNode,
Flow,
true);
1109 bool ExitUseAllowed) {
1110 if (!Order.empty() || !ExitUseAllowed)
1111 return getNextFlow(
Flow);
1115 addPhiValues(
Flow, Exit);
1120void StructurizeCFG::setPrevNode(BasicBlock *BB) {
1126bool StructurizeCFG::dominatesPredicates(BasicBlock *BB, RegionNode *Node) {
1129 Preds, [&](
const auto &Pred) {
return DT->
dominates(BB, Pred.first); });
1133bool StructurizeCFG::isPredictableTrue(RegionNode *Node) {
1135 bool Dominated =
false;
1141 for (
auto [BB, PI] : Preds) {
1142 if (PI.Pred != BoolTrue)
1154void StructurizeCFG::wireFlow(
bool ExitUseAllowed,
1155 BasicBlock *LoopEnd) {
1156 RegionNode *
Node = Order.pop_back_val();
1157 Visited.insert(
Node->getEntry());
1159 if (isPredictableTrue(Node)) {
1162 changeExit(PrevNode,
Node->getEntry(),
true);
1167 auto [
Flow,
DL] = needPrefix(
false);
1176 Conditions.push_back(Br);
1177 addPhiValues(
Flow, Entry);
1181 while (!Order.empty() && !Visited.count(LoopEnd) &&
1182 dominatesPredicates(Entry, Order.back())) {
1183 handleLoops(
false, LoopEnd);
1186 changeExit(PrevNode,
Next,
false);
1191void StructurizeCFG::handleLoops(
bool ExitUseAllowed,
1192 BasicBlock *LoopEnd) {
1193 RegionNode *
Node = Order.back();
1196 if (!
Loops.count(LoopStart)) {
1197 wireFlow(ExitUseAllowed, LoopEnd);
1201 if (!isPredictableTrue(Node))
1202 LoopStart = needPrefix(
true).first;
1205 wireFlow(
false, LoopEnd);
1206 while (!Visited.count(LoopEnd)) {
1207 handleLoops(
false, LoopEnd);
1214 std::tie(LoopEnd,
DL) = needPrefix(
false);
1218 LoopConds.push_back(Br);
1219 addPhiValues(LoopEnd, LoopStart);
1225void StructurizeCFG::createFlow() {
1229 AffectedPhis.clear();
1230 DeletedPhis.clear();
1238 while (!Order.empty()) {
1239 handleLoops(EntryDominatesExit,
nullptr);
1243 changeExit(PrevNode, Exit, EntryDominatesExit);
1245 assert(EntryDominatesExit);
1250void StructurizeCFG::rebuildSSA() {
1252 for (BasicBlock *BB : ParentRegion->
blocks())
1253 for (Instruction &
I : *BB) {
1254 bool Initialized =
false;
1259 if (
User->getParent() == BB) {
1262 if (UserPN->getIncomingBlock(U) == BB)
1284 bool SubRegionsAreUniform =
true;
1286 unsigned ConditionalDirectChildren = 0;
1288 for (
auto *
E : R->elements()) {
1289 if (!
E->isSubRegion()) {
1298 ConditionalDirectChildren++;
1301 <<
" has uniform terminator\n");
1319 if (!ScalarOptions::Global.structurizecfg_relaxed_uniform_regions)
1322 SubRegionsAreUniform =
false;
1335 return SubRegionsAreUniform || (ConditionalDirectChildren <= 1);
1338void StructurizeCFG::init(Region *R) {
1339 LLVMContext &
Context =
R->getEntry()->getContext();
1349bool StructurizeCFG::makeUniformRegion(Region *R,
UniformityInfo &UA) {
1350 if (
R->isTopLevelRegion())
1359 unsigned UniformMDKindID =
1360 R->getEntry()->getContext().getMDKindID(
"structurizecfg.uniform");
1363 LLVM_DEBUG(
dbgs() <<
"Skipping region with uniform control flow: " << *R
1370 MDNode *MD =
MDNode::get(
R->getEntry()->getParent()->getContext(), {});
1371 for (RegionNode *
E :
R->elements()) {
1372 if (
E->isSubRegion())
1375 if (Instruction *Term =
E->getEntry()->getTerminator())
1376 Term->setMetadata(UniformMDKindID, MD);
1385bool StructurizeCFG::run(Region *R, DominatorTree *DT,
1386 const TargetTransformInfo *
TTI) {
1397 Func =
R->getEntry()->getParent();
1405 SSAUpdaterBulk PhiInserter;
1406 insertConditions(
false, PhiInserter);
1407 insertConditions(
true, PhiInserter);
1411 simplifyHoistedPhis();
1412 simplifyConditions();
1413 simplifyAffectedPhis();
1419 DeletedPhis.clear();
1432 return new StructurizeCFGLegacyPass(SkipUniformRegions);
1436 Regions.push_back(&R);
1437 for (
const auto &
E : R)
1442 : SkipUniformRegions(SkipUniformRegions_) {
1443 SkipUniformRegions =
1444 valueOr(ScalarOptions::Global.structurizecfg_skip_uniform_regions,
1445 SkipUniformRegions);
1450 static_cast<PassInfoMixin<StructurizeCFGPass> *
>(
this)->
printPipeline(
1451 OS, MapClassName2PassName);
1452 if (SkipUniformRegions)
1453 OS <<
"<skip-uniform-regions>";
1464 if (SkipUniformRegions)
1467 std::vector<Region *> Regions;
1469 while (!Regions.empty()) {
1470 Region *R = Regions.back();
1473 StructurizeCFG SCFG;
1476 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 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 ...
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.
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...
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.
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)