File indexing completed on 2026-05-10 08:44:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H
0015 #define LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H
0016
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/ADT/ScopeExit.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/Support/Allocator.h"
0021 #include "llvm/Support/Debug.h"
0022 #include "llvm/Support/raw_ostream.h"
0023
0024 #define DEBUG_TYPE "ssaupdater"
0025
0026 namespace llvm {
0027
0028 template<typename T> class SSAUpdaterTraits;
0029
0030 template<typename UpdaterT>
0031 class SSAUpdaterImpl {
0032 private:
0033 UpdaterT *Updater;
0034
0035 using Traits = SSAUpdaterTraits<UpdaterT>;
0036 using BlkT = typename Traits::BlkT;
0037 using ValT = typename Traits::ValT;
0038 using PhiT = typename Traits::PhiT;
0039
0040
0041
0042
0043 class BBInfo {
0044 public:
0045
0046 BlkT *BB;
0047
0048
0049 ValT AvailableVal;
0050
0051
0052 BBInfo *DefBB;
0053
0054
0055 int BlkNum = 0;
0056
0057
0058 BBInfo *IDom = nullptr;
0059
0060
0061 unsigned NumPreds = 0;
0062
0063
0064 BBInfo **Preds = nullptr;
0065
0066
0067 PhiT *PHITag = nullptr;
0068
0069 BBInfo(BlkT *ThisBB, ValT V)
0070 : BB(ThisBB), AvailableVal(V), DefBB(V ? this : nullptr) {}
0071 };
0072
0073 using AvailableValsTy = DenseMap<BlkT *, ValT>;
0074
0075 AvailableValsTy *AvailableVals;
0076
0077 SmallVectorImpl<PhiT *> *InsertedPHIs;
0078
0079 using BlockListTy = SmallVectorImpl<BBInfo *>;
0080 using BBMapTy = DenseMap<BlkT *, BBInfo *>;
0081
0082 BBMapTy BBMap;
0083 BumpPtrAllocator Allocator;
0084
0085 public:
0086 explicit SSAUpdaterImpl(UpdaterT *U, AvailableValsTy *A,
0087 SmallVectorImpl<PhiT *> *Ins) :
0088 Updater(U), AvailableVals(A), InsertedPHIs(Ins) {}
0089
0090
0091
0092
0093
0094 ValT GetValue(BlkT *BB) {
0095 SmallVector<BBInfo *, 100> BlockList;
0096 BBInfo *PseudoEntry = BuildBlockList(BB, &BlockList);
0097
0098
0099 if (BlockList.size() == 0) {
0100 ValT V = Traits::GetPoisonVal(BB, Updater);
0101 (*AvailableVals)[BB] = V;
0102 return V;
0103 }
0104
0105 FindDominators(&BlockList, PseudoEntry);
0106 FindPHIPlacement(&BlockList);
0107 FindAvailableVals(&BlockList);
0108
0109 return BBMap[BB]->DefBB->AvailableVal;
0110 }
0111
0112
0113
0114
0115
0116 BBInfo *BuildBlockList(BlkT *BB, BlockListTy *BlockList) {
0117 SmallVector<BBInfo *, 10> RootList;
0118 SmallVector<BBInfo *, 64> WorkList;
0119
0120 BBInfo *Info = new (Allocator) BBInfo(BB, 0);
0121 BBMap[BB] = Info;
0122 WorkList.push_back(Info);
0123
0124
0125
0126
0127 SmallVector<BlkT *, 10> Preds;
0128 while (!WorkList.empty()) {
0129 Info = WorkList.pop_back_val();
0130 Preds.clear();
0131 Traits::FindPredecessorBlocks(Info->BB, &Preds);
0132 Info->NumPreds = Preds.size();
0133 if (Info->NumPreds == 0)
0134 Info->Preds = nullptr;
0135 else
0136 Info->Preds = static_cast<BBInfo **>(Allocator.Allocate(
0137 Info->NumPreds * sizeof(BBInfo *), alignof(BBInfo *)));
0138
0139 for (unsigned p = 0; p != Info->NumPreds; ++p) {
0140 BlkT *Pred = Preds[p];
0141
0142 BBInfo *&BBMapBucket = BBMap[Pred];
0143 if (BBMapBucket) {
0144 Info->Preds[p] = BBMapBucket;
0145 continue;
0146 }
0147
0148
0149 ValT PredVal = AvailableVals->lookup(Pred);
0150 BBInfo *PredInfo = new (Allocator) BBInfo(Pred, PredVal);
0151 BBMapBucket = PredInfo;
0152 Info->Preds[p] = PredInfo;
0153
0154 if (PredInfo->AvailableVal) {
0155 RootList.push_back(PredInfo);
0156 continue;
0157 }
0158 WorkList.push_back(PredInfo);
0159 }
0160 }
0161
0162
0163
0164
0165 BBInfo *PseudoEntry = new (Allocator) BBInfo(nullptr, 0);
0166 unsigned BlkNum = 1;
0167
0168
0169 while (!RootList.empty()) {
0170 Info = RootList.pop_back_val();
0171 Info->IDom = PseudoEntry;
0172 Info->BlkNum = -1;
0173 WorkList.push_back(Info);
0174 }
0175
0176 while (!WorkList.empty()) {
0177 Info = WorkList.back();
0178
0179 if (Info->BlkNum == -2) {
0180
0181 Info->BlkNum = BlkNum++;
0182
0183 if (!Info->AvailableVal)
0184 BlockList->push_back(Info);
0185 WorkList.pop_back();
0186 continue;
0187 }
0188
0189
0190
0191
0192
0193 Info->BlkNum = -2;
0194
0195
0196 for (typename Traits::BlkSucc_iterator SI =
0197 Traits::BlkSucc_begin(Info->BB),
0198 E = Traits::BlkSucc_end(Info->BB); SI != E; ++SI) {
0199 BBInfo *SuccInfo = BBMap[*SI];
0200 if (!SuccInfo || SuccInfo->BlkNum)
0201 continue;
0202 SuccInfo->BlkNum = -1;
0203 WorkList.push_back(SuccInfo);
0204 }
0205 }
0206 PseudoEntry->BlkNum = BlkNum;
0207 return PseudoEntry;
0208 }
0209
0210
0211
0212
0213
0214 BBInfo *IntersectDominators(BBInfo *Blk1, BBInfo *Blk2) {
0215 while (Blk1 != Blk2) {
0216 while (Blk1->BlkNum < Blk2->BlkNum) {
0217 Blk1 = Blk1->IDom;
0218 if (!Blk1)
0219 return Blk2;
0220 }
0221 while (Blk2->BlkNum < Blk1->BlkNum) {
0222 Blk2 = Blk2->IDom;
0223 if (!Blk2)
0224 return Blk1;
0225 }
0226 }
0227 return Blk1;
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 void FindDominators(BlockListTy *BlockList, BBInfo *PseudoEntry) {
0241 bool Changed;
0242 do {
0243 Changed = false;
0244
0245 for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(),
0246 E = BlockList->rend(); I != E; ++I) {
0247 BBInfo *Info = *I;
0248 BBInfo *NewIDom = nullptr;
0249
0250
0251 for (unsigned p = 0; p != Info->NumPreds; ++p) {
0252 BBInfo *Pred = Info->Preds[p];
0253
0254
0255 if (Pred->BlkNum == 0) {
0256 Pred->AvailableVal = Traits::GetPoisonVal(Pred->BB, Updater);
0257 (*AvailableVals)[Pred->BB] = Pred->AvailableVal;
0258 Pred->DefBB = Pred;
0259 Pred->BlkNum = PseudoEntry->BlkNum;
0260 PseudoEntry->BlkNum++;
0261 }
0262
0263 if (!NewIDom)
0264 NewIDom = Pred;
0265 else
0266 NewIDom = IntersectDominators(NewIDom, Pred);
0267 }
0268
0269
0270 if (NewIDom && NewIDom != Info->IDom) {
0271 Info->IDom = NewIDom;
0272 Changed = true;
0273 }
0274 }
0275 } while (Changed);
0276 }
0277
0278
0279
0280
0281
0282 bool IsDefInDomFrontier(const BBInfo *Pred, const BBInfo *IDom) {
0283 for (; Pred != IDom; Pred = Pred->IDom) {
0284 if (Pred->DefBB == Pred)
0285 return true;
0286 }
0287 return false;
0288 }
0289
0290
0291
0292
0293
0294 void FindPHIPlacement(BlockListTy *BlockList) {
0295 bool Changed;
0296 do {
0297 Changed = false;
0298
0299 for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(),
0300 E = BlockList->rend(); I != E; ++I) {
0301 BBInfo *Info = *I;
0302
0303
0304 if (Info->DefBB == Info)
0305 continue;
0306
0307
0308 BBInfo *NewDefBB = Info->IDom->DefBB;
0309 for (unsigned p = 0; p != Info->NumPreds; ++p) {
0310 if (IsDefInDomFrontier(Info->Preds[p], Info->IDom)) {
0311
0312 NewDefBB = Info;
0313 break;
0314 }
0315 }
0316
0317
0318 if (NewDefBB != Info->DefBB) {
0319 Info->DefBB = NewDefBB;
0320 Changed = true;
0321 }
0322 }
0323 } while (Changed);
0324 }
0325
0326
0327
0328
0329 bool FindSingularVal(BBInfo *Info) {
0330 if (!Info->NumPreds)
0331 return false;
0332 ValT Singular = Info->Preds[0]->DefBB->AvailableVal;
0333 if (!Singular)
0334 return false;
0335 for (unsigned Idx = 1; Idx < Info->NumPreds; ++Idx) {
0336 ValT PredVal = Info->Preds[Idx]->DefBB->AvailableVal;
0337 if (!PredVal || Singular != PredVal)
0338 return false;
0339 }
0340
0341 (*AvailableVals)[Info->BB] = Singular;
0342 assert(BBMap[Info->BB] == Info && "Info missed in BBMap?");
0343 Info->AvailableVal = Singular;
0344 Info->DefBB = Info->Preds[0]->DefBB;
0345 return true;
0346 }
0347
0348
0349
0350
0351
0352
0353 void FindAvailableVals(BlockListTy *BlockList) {
0354
0355
0356
0357 for (typename BlockListTy::iterator I = BlockList->begin(),
0358 E = BlockList->end(); I != E; ++I) {
0359 BBInfo *Info = *I;
0360
0361 if (Info->DefBB != Info)
0362 continue;
0363
0364
0365 if (FindSingularVal(Info))
0366 continue;
0367
0368
0369 FindExistingPHI(Info->BB, BlockList);
0370 if (Info->AvailableVal)
0371 continue;
0372
0373 ValT PHI = Traits::CreateEmptyPHI(Info->BB, Info->NumPreds, Updater);
0374 Info->AvailableVal = PHI;
0375 (*AvailableVals)[Info->BB] = PHI;
0376 }
0377
0378
0379
0380 for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(),
0381 E = BlockList->rend(); I != E; ++I) {
0382 BBInfo *Info = *I;
0383
0384 if (Info->DefBB != Info) {
0385
0386
0387 (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal;
0388 continue;
0389 }
0390
0391
0392 PhiT *PHI = Traits::ValueIsNewPHI(Info->AvailableVal, Updater);
0393 if (!PHI)
0394 continue;
0395
0396
0397 for (unsigned p = 0; p != Info->NumPreds; ++p) {
0398 BBInfo *PredInfo = Info->Preds[p];
0399 BlkT *Pred = PredInfo->BB;
0400
0401 if (PredInfo->DefBB != PredInfo)
0402 PredInfo = PredInfo->DefBB;
0403 Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred);
0404 }
0405
0406 LLVM_DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n");
0407
0408
0409 if (InsertedPHIs) InsertedPHIs->push_back(PHI);
0410 }
0411 }
0412
0413
0414
0415 void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) {
0416 SmallVector<BBInfo *, 20> TaggedBlocks;
0417 for (auto &SomePHI : BB->phis()) {
0418 if (CheckIfPHIMatches(&SomePHI, TaggedBlocks)) {
0419 RecordMatchingPHIs(BlockList);
0420 break;
0421 }
0422 }
0423 }
0424
0425
0426
0427 bool CheckIfPHIMatches(PhiT *PHI, SmallVectorImpl<BBInfo *> &TaggedBlocks) {
0428
0429
0430 auto Cleanup = make_scope_exit([&]() {
0431 for (BBInfo *TaggedBlock : TaggedBlocks)
0432 TaggedBlock->PHITag = nullptr;
0433 TaggedBlocks.clear();
0434 });
0435
0436 SmallVector<PhiT *, 20> WorkList;
0437 WorkList.push_back(PHI);
0438
0439
0440 BBInfo *PHIBlock = BBMap[PHI->getParent()];
0441 PHIBlock->PHITag = PHI;
0442 TaggedBlocks.push_back(PHIBlock);
0443
0444 while (!WorkList.empty()) {
0445 PHI = WorkList.pop_back_val();
0446
0447
0448 for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI),
0449 E = Traits::PHI_end(PHI); I != E; ++I) {
0450 ValT IncomingVal = I.getIncomingValue();
0451 BBInfo *PredInfo = BBMap[I.getIncomingBlock()];
0452
0453 if (PredInfo->DefBB != PredInfo)
0454 PredInfo = PredInfo->DefBB;
0455
0456
0457 if (PredInfo->AvailableVal) {
0458 if (IncomingVal == PredInfo->AvailableVal)
0459 continue;
0460 return false;
0461 }
0462
0463
0464 PhiT *IncomingPHIVal = Traits::ValueIsPHI(IncomingVal, Updater);
0465 if (!IncomingPHIVal || IncomingPHIVal->getParent() != PredInfo->BB)
0466 return false;
0467
0468
0469 if (PredInfo->PHITag) {
0470 if (IncomingPHIVal == PredInfo->PHITag)
0471 continue;
0472 return false;
0473 }
0474 PredInfo->PHITag = IncomingPHIVal;
0475 TaggedBlocks.push_back(PredInfo);
0476
0477 WorkList.push_back(IncomingPHIVal);
0478 }
0479 }
0480
0481 Cleanup.release();
0482 return true;
0483 }
0484
0485
0486
0487 void RecordMatchingPHIs(BlockListTy *BlockList) {
0488 for (typename BlockListTy::iterator I = BlockList->begin(),
0489 E = BlockList->end(); I != E; ++I)
0490 if (PhiT *PHI = (*I)->PHITag) {
0491 BlkT *BB = PHI->getParent();
0492 ValT PHIVal = Traits::GetPHIValue(PHI);
0493 (*AvailableVals)[BB] = PHIVal;
0494 BBMap[BB]->AvailableVal = PHIVal;
0495 }
0496 }
0497 };
0498
0499 }
0500
0501 #undef DEBUG_TYPE
0502
0503 #endif