File indexing completed on 2026-05-10 08:43:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
0017 #define LLVM_ANALYSIS_GENERICDOMTREEUPDATERIMPL_H
0018
0019 #include "llvm/ADT/SmallBitVector.h"
0020 #include "llvm/Analysis/GenericDomTreeUpdater.h"
0021 #include "llvm/Support/Debug.h"
0022 #include "llvm/Support/raw_ostream.h"
0023
0024 namespace llvm {
0025
0026 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0027 template <typename FuncT>
0028 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::recalculate(
0029 FuncT &F) {
0030 if (Strategy == UpdateStrategy::Eager) {
0031 if (DT)
0032 DT->recalculate(F);
0033 if (PDT)
0034 PDT->recalculate(F);
0035 return;
0036 }
0037
0038
0039
0040
0041
0042 IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
0043
0044
0045
0046 derived().forceFlushDeletedBB();
0047 if (DT)
0048 DT->recalculate(F);
0049 if (PDT)
0050 PDT->recalculate(F);
0051
0052
0053 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
0054 PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
0055 dropOutOfDateUpdates();
0056 }
0057
0058 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0059 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::applyUpdates(
0060 ArrayRef<UpdateT> Updates) {
0061 if (!DT && !PDT)
0062 return;
0063
0064 if (Strategy == UpdateStrategy::Lazy) {
0065 PendUpdates.reserve(PendUpdates.size() + Updates.size());
0066 for (const auto &U : Updates)
0067 if (!isSelfDominance(U))
0068 PendUpdates.push_back(U);
0069
0070 return;
0071 }
0072
0073 if (DT)
0074 DT->applyUpdates(Updates);
0075 if (PDT)
0076 PDT->applyUpdates(Updates);
0077 }
0078
0079 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0080 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
0081 applyUpdatesPermissive(ArrayRef<UpdateT> Updates) {
0082 if (!DT && !PDT)
0083 return;
0084
0085 SmallSet<std::pair<BasicBlockT *, BasicBlockT *>, 8> Seen;
0086 SmallVector<UpdateT, 8> DeduplicatedUpdates;
0087 for (const auto &U : Updates) {
0088 auto Edge = std::make_pair(U.getFrom(), U.getTo());
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 if (!isSelfDominance(U) && Seen.insert(Edge).second) {
0112
0113
0114
0115 if (isUpdateValid(U)) {
0116 if (isLazy())
0117 PendUpdates.push_back(U);
0118 else
0119 DeduplicatedUpdates.push_back(U);
0120 }
0121 }
0122 }
0123
0124 if (Strategy == UpdateStrategy::Lazy)
0125 return;
0126
0127 if (DT)
0128 DT->applyUpdates(DeduplicatedUpdates);
0129 if (PDT)
0130 PDT->applyUpdates(DeduplicatedUpdates);
0131 }
0132
0133 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0134 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::splitCriticalEdge(
0135 BasicBlockT *FromBB, BasicBlockT *ToBB, BasicBlockT *NewBB) {
0136 if (!DT && !PDT)
0137 return;
0138
0139 CriticalEdge E = {FromBB, ToBB, NewBB};
0140 if (Strategy == UpdateStrategy::Lazy) {
0141 PendUpdates.push_back(E);
0142 return;
0143 }
0144
0145 if (DT)
0146 splitDTCriticalEdges(E);
0147 if (PDT)
0148 splitPDTCriticalEdges(E);
0149 }
0150
0151 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0152 DomTreeT &
0153 GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::getDomTree() {
0154 assert(DT && "Invalid acquisition of a null DomTree");
0155 applyDomTreeUpdates();
0156 dropOutOfDateUpdates();
0157 return *DT;
0158 }
0159
0160 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0161 PostDomTreeT &
0162 GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::getPostDomTree() {
0163 assert(PDT && "Invalid acquisition of a null PostDomTree");
0164 applyPostDomTreeUpdates();
0165 dropOutOfDateUpdates();
0166 return *PDT;
0167 }
0168
0169 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0170 LLVM_DUMP_METHOD void
0171 GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::dump() const {
0172 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0173 raw_ostream &OS = llvm::dbgs();
0174
0175 OS << "Available Trees: ";
0176 if (DT || PDT) {
0177 if (DT)
0178 OS << "DomTree ";
0179 if (PDT)
0180 OS << "PostDomTree ";
0181 OS << "\n";
0182 } else
0183 OS << "None\n";
0184
0185 OS << "UpdateStrategy: ";
0186 if (Strategy == UpdateStrategy::Eager) {
0187 OS << "Eager\n";
0188 return;
0189 } else
0190 OS << "Lazy\n";
0191 int Index = 0;
0192
0193 auto printBlockInfo = [&](BasicBlockT *BB, StringRef Ending) {
0194 if (BB) {
0195 auto S = BB->getName();
0196 if (!BB->hasName())
0197 S = "(no name)";
0198 OS << S << "(" << BB << ")" << Ending;
0199 } else {
0200 OS << "(badref)" << Ending;
0201 }
0202 };
0203
0204 auto printUpdates =
0205 [&](typename ArrayRef<DomTreeUpdate>::const_iterator begin,
0206 typename ArrayRef<DomTreeUpdate>::const_iterator end) {
0207 if (begin == end)
0208 OS << " None\n";
0209 Index = 0;
0210 for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
0211 if (!It->IsCriticalEdgeSplit) {
0212 auto U = It->Update;
0213 OS << " " << Index << " : ";
0214 ++Index;
0215 if (U.getKind() == DomTreeT::Insert)
0216 OS << "Insert, ";
0217 else
0218 OS << "Delete, ";
0219 printBlockInfo(U.getFrom(), ", ");
0220 printBlockInfo(U.getTo(), "\n");
0221 } else {
0222 const auto &Edge = It->EdgeSplit;
0223 OS << " " << Index++ << " : Split critical edge, ";
0224 printBlockInfo(Edge.FromBB, ", ");
0225 printBlockInfo(Edge.ToBB, ", ");
0226 printBlockInfo(Edge.NewBB, "\n");
0227 }
0228 }
0229 };
0230
0231 if (DT) {
0232 const auto I = PendUpdates.begin() + PendDTUpdateIndex;
0233 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
0234 "Iterator out of range.");
0235 OS << "Applied but not cleared DomTreeUpdates:\n";
0236 printUpdates(PendUpdates.begin(), I);
0237 OS << "Pending DomTreeUpdates:\n";
0238 printUpdates(I, PendUpdates.end());
0239 }
0240
0241 if (PDT) {
0242 const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
0243 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
0244 "Iterator out of range.");
0245 OS << "Applied but not cleared PostDomTreeUpdates:\n";
0246 printUpdates(PendUpdates.begin(), I);
0247 OS << "Pending PostDomTreeUpdates:\n";
0248 printUpdates(I, PendUpdates.end());
0249 }
0250
0251 OS << "Pending DeletedBBs:\n";
0252 Index = 0;
0253 for (const auto *BB : DeletedBBs) {
0254 OS << " " << Index << " : ";
0255 ++Index;
0256 if (BB->hasName())
0257 OS << BB->getName() << "(";
0258 else
0259 OS << "(no name)(";
0260 OS << BB << ")\n";
0261 }
0262 #endif
0263 }
0264
0265 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0266 template <bool IsForward>
0267 void GenericDomTreeUpdater<DerivedT, DomTreeT,
0268 PostDomTreeT>::applyUpdatesImpl() {
0269 auto *DomTree = [&]() {
0270 if constexpr (IsForward)
0271 return DT;
0272 else
0273 return PDT;
0274 }();
0275
0276 if (Strategy != UpdateStrategy::Lazy || !DomTree)
0277 return;
0278 size_t &PendUpdateIndex = IsForward ? PendDTUpdateIndex : PendPDTUpdateIndex;
0279
0280
0281 while (IsForward ? hasPendingDomTreeUpdates()
0282 : hasPendingPostDomTreeUpdates()) {
0283 auto I = PendUpdates.begin() + PendUpdateIndex;
0284 const auto E = PendUpdates.end();
0285 assert(I < E && "Iterator range invalid; there should be DomTree updates.");
0286 if (!I->IsCriticalEdgeSplit) {
0287 SmallVector<UpdateT, 32> NormalUpdates;
0288 for (; I != E && !I->IsCriticalEdgeSplit; ++I)
0289 NormalUpdates.push_back(I->Update);
0290 DomTree->applyUpdates(NormalUpdates);
0291 PendUpdateIndex += NormalUpdates.size();
0292 } else {
0293 SmallVector<CriticalEdge> CriticalEdges;
0294 for (; I != E && I->IsCriticalEdgeSplit; ++I)
0295 CriticalEdges.push_back(I->EdgeSplit);
0296 IsForward ? splitDTCriticalEdges(CriticalEdges)
0297 : splitPDTCriticalEdges(CriticalEdges);
0298 PendUpdateIndex += CriticalEdges.size();
0299 }
0300 }
0301 }
0302
0303 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0304 bool GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::isUpdateValid(
0305 UpdateT Update) const {
0306 const auto *From = Update.getFrom();
0307 const auto *To = Update.getTo();
0308 const auto Kind = Update.getKind();
0309
0310
0311
0312
0313
0314 const bool HasEdge = llvm::is_contained(successors(From), To);
0315
0316
0317
0318
0319
0320 if (Kind == DomTreeT::Insert && !HasEdge)
0321 return false;
0322
0323
0324 if (Kind == DomTreeT::Delete && HasEdge)
0325 return false;
0326
0327 return true;
0328 }
0329
0330 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0331 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::eraseDelBBNode(
0332 BasicBlockT *DelBB) {
0333 if (DT && !IsRecalculatingDomTree)
0334 if (DT->getNode(DelBB))
0335 DT->eraseNode(DelBB);
0336
0337 if (PDT && !IsRecalculatingPostDomTree)
0338 if (PDT->getNode(DelBB))
0339 PDT->eraseNode(DelBB);
0340 }
0341
0342 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0343 void GenericDomTreeUpdater<DerivedT, DomTreeT,
0344 PostDomTreeT>::tryFlushDeletedBB() {
0345 if (!hasPendingUpdates())
0346 derived().forceFlushDeletedBB();
0347 }
0348
0349 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0350 void GenericDomTreeUpdater<DerivedT, DomTreeT,
0351 PostDomTreeT>::dropOutOfDateUpdates() {
0352 if (Strategy == UpdateStrategy::Eager)
0353 return;
0354
0355 tryFlushDeletedBB();
0356
0357
0358 if (!DT)
0359 PendDTUpdateIndex = PendUpdates.size();
0360 if (!PDT)
0361 PendPDTUpdateIndex = PendUpdates.size();
0362
0363 const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
0364 const auto B = PendUpdates.begin();
0365 const auto E = PendUpdates.begin() + dropIndex;
0366 assert(B <= E && "Iterator out of range.");
0367 PendUpdates.erase(B, E);
0368
0369 PendDTUpdateIndex -= dropIndex;
0370 PendPDTUpdateIndex -= dropIndex;
0371 }
0372
0373 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0374 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
0375 splitDTCriticalEdges(ArrayRef<CriticalEdge> Edges) {
0376
0377 if (!DT || Edges.empty())
0378 return;
0379
0380
0381
0382
0383
0384
0385
0386 SmallSet<BasicBlockT *, 32> NewBBs;
0387 for (auto &Edge : Edges)
0388 NewBBs.insert(Edge.NewBB);
0389
0390
0391
0392
0393 SmallBitVector IsNewIDom(Edges.size(), true);
0394
0395
0396
0397 for (const auto &[Idx, Edge] : enumerate(Edges)) {
0398
0399 BasicBlockT *Succ = Edge.ToBB;
0400 auto *SuccDTNode = DT->getNode(Succ);
0401
0402 for (BasicBlockT *PredBB : predecessors(Succ)) {
0403 if (PredBB == Edge.NewBB)
0404 continue;
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 if (NewBBs.contains(PredBB)) {
0419 assert(pred_size(PredBB) == 1 && "A basic block resulting from a "
0420 "critical edge split has more "
0421 "than one predecessor!");
0422 PredBB = *pred_begin(PredBB);
0423 }
0424 if (!DT->dominates(SuccDTNode, DT->getNode(PredBB))) {
0425 IsNewIDom[Idx] = false;
0426 break;
0427 }
0428 }
0429 }
0430
0431
0432 for (const auto &[Idx, Edge] : enumerate(Edges)) {
0433
0434 auto *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB);
0435
0436
0437
0438
0439 if (IsNewIDom[Idx])
0440 DT->changeImmediateDominator(DT->getNode(Edge.ToBB), NewDTNode);
0441 }
0442 }
0443
0444
0445
0446 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT>
0447 void GenericDomTreeUpdater<DerivedT, DomTreeT, PostDomTreeT>::
0448 splitPDTCriticalEdges(ArrayRef<CriticalEdge> Edges) {
0449
0450 if (!PDT || Edges.empty())
0451 return;
0452
0453 std::vector<UpdateT> Updates;
0454 for (const auto &Edge : Edges) {
0455 Updates.push_back({PostDomTreeT::Insert, Edge.FromBB, Edge.NewBB});
0456 Updates.push_back({PostDomTreeT::Insert, Edge.NewBB, Edge.ToBB});
0457 if (!llvm::is_contained(successors(Edge.FromBB), Edge.ToBB))
0458 Updates.push_back({PostDomTreeT::Delete, Edge.FromBB, Edge.ToBB});
0459 }
0460 PDT->applyUpdates(Updates);
0461 }
0462
0463 }
0464
0465 #endif