LLVM: include/llvm/Support/GenericDomTreeConstruction.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H

38#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H

39

46#include

47#include

48

49#define DEBUG_TYPE "dom-tree-builder"

50

51namespace llvm {

52namespace DomTreeBuilder {

53

54template

56 using NodePtr = typename DomTreeT::NodePtr;

57 using NodeT = typename DomTreeT::NodeType;

59 using RootsT = decltype(DomTreeT::Roots);

60 static constexpr bool IsPostDom = DomTreeT::IsPostDominator;

62

63

71 };

72

73

74

76

77

81

82 using UpdateT = typename DomTreeT::UpdateType;

83 using UpdateKind = typename DomTreeT::UpdateKind;

85

89

90

91

96 };

97

100

101

103

105 NumToNode = {nullptr};

107

108

109 }

110

111 template

113 if (BUI)

114 return BUI->PreViewCFG.template getChildren(N);

115 return getChildren(N);

116 }

117

118 template

120 using DirectedNodeT =

121 std::conditional_t<Inversed, Inverse, NodePtr>;

122 auto R = children(N);

124

125

127 return Res;

128 }

129

131 if constexpr (GraphHasNodeNumbers) {

134 unsigned Max = 0;

135 if (BB)

136 Max = GraphTraits<decltype(BB->getParent())>::getMaxNumber(

137 BB->getParent());

138

140 }

142 } else {

144 }

145 }

146

148

151

152

153

155

156 assert(IDom || DT.getNode(nullptr));

158

159

160

161 return DT.createNode(BB, IDomNode);

162 }

163

165

168

171

173 if (!BP.N)

174 O << "nullptr";

175 else

176 BP.N->printAsOperand(O, false);

177

178 return O;

179 }

180 };

181

183

184

185

186

187

188

189

190

191

192

193

194 template

195 unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition,

196 unsigned AttachToNum,

201

202 while (!WorkList.empty()) {

203 const auto [BB, ParentNum] = WorkList.pop_back_val();

205 BBInfo.ReverseChildren.push_back(ParentNum);

206

207

208 if (BBInfo.DFSNum != 0) continue;

209 BBInfo.Parent = ParentNum;

210 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = ++LastNum;

212

214 auto Successors = getChildren(BB, BatchUpdates);

215 if (SuccOrder && Successors.size() > 1)

217 Successors.begin(), Successors.end(), [=](NodePtr A, NodePtr B) {

218 return SuccOrder->find(A)->second < SuccOrder->find(B)->second;

219 });

220

221 for (const NodePtr Succ : Successors) {

222 if (!Condition(BB, Succ)) continue;

223

224 WorkList.push_back({Succ, LastNum});

225 }

226 }

227

228 return LastNum;

229 }

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244 unsigned eval(unsigned V, unsigned LastLinked,

247 InfoRec *VInfo = NumToInfo[V];

248 if (VInfo->Parent < LastLinked)

249 return VInfo->Label;

250

251

252 assert(Stack.empty());

253 do {

254 Stack.push_back(VInfo);

255 VInfo = NumToInfo[VInfo->Parent];

256 } while (VInfo->Parent >= LastLinked);

257

258

259

260 const InfoRec *PInfo = VInfo;

261 const InfoRec *PLabelInfo = NumToInfo[PInfo->Label];

262 do {

263 VInfo = Stack.pop_back_val();

265 const InfoRec *VLabelInfo = NumToInfo[VInfo->Label];

266 if (PLabelInfo->Semi < VLabelInfo->Semi)

268 else

269 PLabelInfo = VLabelInfo;

270 PInfo = VInfo;

271 } while (!Stack.empty());

272 return VInfo->Label;

273 }

274

275

279 NumToInfo.reserve(NextDFSNum);

280

281 for (unsigned i = 1; i < NextDFSNum; ++i) {

284 VInfo.IDom = NumToNode[VInfo.Parent];

286 }

287

288

290 for (unsigned i = NextDFSNum - 1; i >= 2; --i) {

291 auto &WInfo = *NumToInfo[i];

292

293

294 WInfo.Semi = WInfo.Parent;

295 for (unsigned N : WInfo.ReverseChildren) {

296 unsigned SemiU = NumToInfo[eval(N, i + 1, EvalStack, NumToInfo)]->Semi;

297 if (SemiU < WInfo.Semi) WInfo.Semi = SemiU;

298 }

299 }

300

301

302

303

304

305 for (unsigned i = 2; i < NextDFSNum; ++i) {

306 auto &WInfo = *NumToInfo[i];

307 assert(WInfo.Semi != 0);

308 const unsigned SDomNum = NumToInfo[WInfo.Semi]->DFSNum;

309 NodePtr WIDomCandidate = WInfo.IDom;

310 while (true) {

311 auto &WIDomCandidateInfo = getNodeInfo(WIDomCandidate);

312 if (WIDomCandidateInfo.DFSNum <= SDomNum)

313 break;

314 WIDomCandidate = WIDomCandidateInfo.IDom;

315 }

316

317 WInfo.IDom = WIDomCandidate;

318 }

319 }

320

321

322

323

324

325

327 assert(IsPostDom && "Only postdominators have a virtual root");

329

331 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = 1;

332

334 }

335

336

337

338

340 assert(N && "N must be a valid node");

341 return !getChildren(N, BUI).empty();

342 }

343

345 assert(DT.Parent && "Parent not set");

347 }

348

349

350

351

353 assert(DT.Parent && "Parent pointer is not set");

355

356

359 return Roots;

360 }

361

363

364

366 unsigned Num = 1;

367

368 LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n");

369

370

371

372 unsigned Total = 0;

373

374

375

376

377

380

382 Roots.push_back(N);

383

386 << "\n");

389 }

390 }

391

392 LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n");

393

394

395

396

397 bool HasNonTrivialRoots = false;

398

399

400 if (Total + 1 != Num) {

401 HasNonTrivialRoots = true;

402

403

404

405

406

407

408 std::optional SuccOrder;

409 auto InitSuccOrderOnce = [&]() {

411 for (const auto Node : nodes(DT.Parent))

413 for (const auto Succ : getChildren(Node, SNCA.BatchUpdates))

414 SuccOrder->try_emplace(Succ, 0);

415

416

417 unsigned NodeNum = 0;

418 for (const auto Node : nodes(DT.Parent)) {

419 ++NodeNum;

420 auto Order = SuccOrder->find(Node);

421 if (Order != SuccOrder->end()) {

422 assert(Order->second == 0);

423 Order->second = NodeNum;

424 }

425 }

426 };

427

428

429

430

431

432

433

434

439

440

441

442

443

444

445

446

447

448

450

451 if (!SuccOrder)

452 InitSuccOrderOnce();

454

455 const unsigned NewNum =

458 LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node "

459 << "(non-trivial root): "

461 Roots.push_back(FurthestAway);

462 LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: "

463 << NewNum << "\n\t\t\tRemoving DFS info\n");

464 for (unsigned i = NewNum; i > Num; --i) {

466 LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for "

470 }

471 const unsigned PrevNum = Num;

474 for (unsigned i = PrevNum + 1; i <= Num; ++i)

477 }

478 }

479 }

480

485

486 assert((Total + 1 == Num) && "Everything should have been visited");

487

488

490

493 : Roots) dbgs()

496

497 return Roots;

498 }

499

500

501

502

503

504

505

506

507

510 assert(IsPostDom && "This function is for postdominators only");

512

514

515 for (unsigned i = 0; i < Roots.size(); ++i) {

516 auto &Root = Roots[i];

517

520 << " remains a root\n");

522

524

525

526 for (unsigned x = 2; x <= Num; ++x) {

528

529

530

532 LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root "

536 Roots.pop_back();

537

538

539

540 --i;

541 break;

542 }

543 }

544 }

545 }

546

547 template

548 void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) {

550 assert(DT.Roots.size() == 1 && "Dominators should have a singe root");

551 runDFS(DT.Roots[0], 0, DC, 0);

552 return;

553 }

554

556 unsigned Num = 1;

557 for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 1);

558 }

559

561 auto *Parent = DT.Parent;

562 DT.reset();

563 DT.Parent = Parent;

564

565

566

570 PostViewBUI = BUI;

571 }

572

573

575

576

577

578 DT.Roots = FindRoots(DT, PostViewBUI);

580

582 if (BUI) {

585 dbgs() << "DomTree recalculated, skipping future batch updates\n");

586 }

587

588 if (DT.Roots.empty()) return;

589

590

591

592

594

595 DT.RootNode = DT.createNode(Root);

597 }

598

600

602

604 if (DT.getNode(W))

605 continue;

606

608

609

611

612

613

614 DT.createNode(W, IDomNode);

615 }

616 }

617

625 }

626 }

627

628

632 return LHS->getLevel() < RHS->getLevel();

633 }

634 };

635

636

637

638 std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>,

639 Compare>

643#if LLVM_ENABLE_ABI_BREAKING_CHECKS

645#endif

646 };

647

651 "From has to be a valid CFG node or a virtual root");

652 assert(To && "Cannot be a nullptr");

656

657 if (!FromTN) {

658

660

661

662 TreeNodePtr VirtualRoot = DT.getNode(nullptr);

663 FromTN = DT.createNode(From, VirtualRoot);

664 DT.Roots.push_back(From);

665 }

666

667 DT.DFSInfoValid = false;

668

670 if (!ToTN)

672 else

674 }

675

676

677

681 assert(IsPostDom && "This function is only for postdominators");

682

683

684 if (!DT.isVirtualRoot(To->getIDom())) return false;

685

687 return false;

688

690 << " is no longer a root\n\t\tRebuilding the tree!!!\n");

691

693 return true;

694 }

695

698 if (A.size() != B.size())

699 return false;

702 if (Set.count(N) == 0)

703 return false;

704 return true;

705 }

706

707

708

709

711 assert(IsPostDom && "This function is only for postdominators");

712

713

715 return HasForwardSuccessors(N, BUI);

716 }))

717 return;

718

719

722

723

724

725

726

727 LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n"

728 << "The entire tree needs to be rebuilt\n");

729

730

732 }

733 }

734

735

741

742

743

746 ? DT.findNearestCommonDominator(From->getBlock(), To->getBlock())

747 : nullptr;

748 assert(NCDBlock || DT.isPostDominator());

749 const TreeNodePtr NCD = DT.getNode(NCDBlock);

751

753 const unsigned NCDLevel = NCD->getLevel();

754

755

756

757

758

759

760

761

762

763

764

765 if (NCDLevel + 1 >= To->getLevel())

766 return;

767

770 II.Bucket.push(To);

771 II.Visited.insert(To);

772

773 while (II.Bucket.empty()) {

775 II.Bucket.pop();

776 II.Affected.push_back(TN);

777

778 const unsigned CurrentLevel = TN->getLevel();

780 "as affected, CurrentLevel " << CurrentLevel << "\n");

781

782 assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");

783

784 while (true) {

785

786

787

788

789

790

791

792

793 for (const NodePtr Succ : getChildren(TN->getBlock(), BUI)) {

794 const TreeNodePtr SuccTN = DT.getNode(Succ);

796 "Unreachable successor found at reachable insertion");

797 const unsigned SuccLevel = SuccTN->getLevel();

798

800 << ", level = " << SuccLevel << "\n");

801

802

803

804

805

806

807

808

809 if (SuccLevel <= NCDLevel + 1 || II.Visited.insert(SuccTN).second)

810 continue;

811

812 if (SuccLevel > CurrentLevel) {

813

814

815 LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected "

817 UnaffectedOnCurrentLevel.push_back(SuccTN);

818#if LLVM_ENABLE_ABI_BREAKING_CHECKS

819 II.VisitedUnaffected.push_back(SuccTN);

820#endif

821 } else {

822

823

825 << " to a Bucket\n");

826 II.Bucket.push(SuccTN);

827 }

828 }

829

830 if (UnaffectedOnCurrentLevel.empty())

831 break;

832 TN = UnaffectedOnCurrentLevel.pop_back_val();

834 }

835 }

836

837

839 }

840

841

845

850 }

851

852#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)

853 for (const TreeNodePtr TN : II.VisitedUnaffected)

855 "TN should have been updated by an affected ancestor");

856#endif

857

859 }

860

861

866

867

869

871

874 << "\n");

875

876

877

878 for (const auto &Edge : DiscoveredEdgesToReachable) {

879 LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge "

882 InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second);

883 }

884 }

885

886

891 &DiscoveredConnectingEdges) {

892 assert(!DT.getNode(Root) && "Root must not be reachable");

893

894

895 auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From,

898 if (!ToTN) return true;

899

900 DiscoveredConnectingEdges.push_back({From, ToTN});

901 return false;

902 };

903

905 SNCA.runDFS(Root, 0, UnreachableDescender, 0);

908

909 LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n");

910 }

911

914 assert(From && To && "Cannot disconnect nullptrs");

917

918#if LLVM_ENABLE_ABI_BREAKING_CHECKS

919

920

921

922 auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) {

923 auto Successors = getChildren(Of, BUI);

925 };

926 (void)IsSuccessor;

927 assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!");

928#endif

929

931

932 if (!FromTN) return;

933

935 if (!ToTN) {

938 << ") already unreachable -- there is no edge to delete\n");

939 return;

940 }

941

942 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);

943 const TreeNodePtr NCD = DT.getNode(NCDBlock);

944

945

946 if (ToTN != NCD) {

947 DT.DFSInfoValid = false;

948

952

953

954

957 else

959 }

960

962 }

963

964

971

972

973

975 DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock());

976 assert(ToIDom || DT.isPostDominator());

977 const TreeNodePtr ToIDomTN = DT.getNode(ToIDom);

980

981

982 if (!PrevIDomSubTree) {

983 LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");

985 return;

986 }

987

988

989 const unsigned Level = ToIDomTN->getLevel();

990 auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) {

991 return DT.getNode(To)->getLevel() > Level;

992 };

993

995 << "\n");

996

998 SNCA.runDFS(ToIDom, 0, DescendBelow, 0);

1002 }

1003

1004

1005

1009 << "\n");

1011 for (const NodePtr Pred : getChildren<!IsPostDom>(TNB, BUI)) {

1013 if (!DT.getNode(Pred)) continue;

1014

1015 const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);

1017 if (Support != TNB) {

1019 << " is reachable from support "

1021 return true;

1022 }

1023 }

1024

1025 return false;

1026 }

1027

1028

1029

1032 LLVM_DEBUG(dbgs() << "Deleting unreachable subtree "

1036

1038

1039

1040

1041 LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n");

1043 << "\n");

1044 DT.Roots.push_back(ToTN->getBlock());

1046 return;

1047 }

1048

1050 const unsigned Level = ToTN->getLevel();

1051

1052

1053

1054 auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) {

1057 if (TN->getLevel() > Level) return true;

1060

1061 return false;

1062 };

1063

1065 unsigned LastDFSNum =

1066 SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);

1067

1069

1070

1071

1072 for (const NodePtr N : AffectedQueue) {

1074 const NodePtr NCDBlock =

1075 DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock());

1076 assert(NCDBlock || DT.isPostDominator());

1077 const TreeNodePtr NCD = DT.getNode(NCDBlock);

1079

1083 if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD;

1084 }

1085

1086

1087 if (!MinNode->getIDom()) {

1088 LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");

1090 return;

1091 }

1092

1093

1094

1095 for (unsigned i = LastDFSNum; i > 0; --i) {

1098 << "\n");

1099 DT.eraseNode(N);

1100 }

1101

1102

1103 if (MinNode == ToTN) return;

1104

1105 LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = "

1107 const unsigned MinLevel = MinNode->getLevel();

1111

1112

1113 auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) {

1114 const TreeNodePtr ToTN = DT.getNode(To);

1115 return ToTN && ToTN->getLevel() > MinLevel;

1116 };

1117 SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);

1118

1121

1122

1125 }

1126

1127

1128

1129

1130

1133

1134

1136 if (NumUpdates == 0)

1137 return;

1138

1139

1140

1141 if (NumUpdates == 1) {

1143 if (!PostViewCFG) {

1144 if (Update.getKind() == UpdateKind::Insert)

1145 InsertEdge(DT, nullptr, Update.getFrom(), Update.getTo());

1146 else

1147 DeleteEdge(DT, nullptr, Update.getFrom(), Update.getTo());

1148 } else {

1150 if (Update.getKind() == UpdateKind::Insert)

1151 InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());

1152 else

1153 DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());

1154 }

1155 return;

1156 }

1157

1159

1160

1161

1162

1163

1164

1165

1166

1167 if (DT.DomTreeNodes.size() <= 100) {

1168 if (BUI.NumLegalized > DT.DomTreeNodes.size())

1170 } else if (BUI.NumLegalized > DT.DomTreeNodes.size() / 40)

1172

1173

1174

1175

1178 }

1179

1181

1183#if 0

1184

1185

1186

1189#endif

1190

1191 if (CurrentUpdate.getKind() == UpdateKind::Insert)

1192 InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());

1193 else

1194 DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());

1195 }

1196

1197

1198

1199

1200

1201

1202

1203

1204

1205

1207 if (!DT.Parent && !DT.Roots.empty()) {

1208 errs() << "Tree has no parent but has roots!\n";

1210 return false;

1211 }

1212

1214 if (DT.Roots.empty()) {

1215 errs() << "Tree doesn't have a root!\n";

1217 return false;

1218 }

1219

1221 errs() << "Tree's root is not its parent's entry node!\n";

1223 return false;

1224 }

1225 }

1226

1229 errs() << "Tree has different roots than freshly computed ones!\n";

1230 errs() << "\tPDT roots: ";

1232 errs() << "\n\tComputed roots: ";

1233 for (const NodePtr N : ComputedRoots)

1235 errs() << "\n";

1237 return false;

1238 }

1239

1240 return true;

1241 }

1242

1243

1244

1248

1249 for (auto &NodeToTN : DT.DomTreeNodes) {

1251 if (!TN)

1252 continue;

1254

1255

1256 if (DT.isVirtualRoot(TN)) continue;

1257

1260 << " not found by DFS walk!\n";

1262

1263 return false;

1264 }

1265 }

1266

1268 if (N && !DT.getNode(N)) {

1270 << " not found in the DomTree!\n";

1272

1273 return false;

1274 }

1275 }

1276

1277 return true;

1278 }

1279

1280

1281

1282

1284 for (auto &NodeToTN : DT.DomTreeNodes) {

1286 if (!TN)

1287 continue;

1289 if (!BB) continue;

1290

1292 if (!IDom && TN->getLevel() != 0) {

1294 << " has a nonzero level " << TN->getLevel() << "!\n";

1296

1297 return false;

1298 }

1299

1302 << TN->getLevel() << " while its IDom "

1304 << IDom->getLevel() << "!\n";

1306

1307 return false;

1308 }

1309 }

1310

1311 return true;

1312 }

1313

1314

1315

1316

1318 if (!DT.DFSInfoValid || !DT.Parent)

1319 return true;

1320

1321 const NodePtr RootBB = IsPostDom ? nullptr : *DT.root_begin();

1322 const TreeNodePtr Root = DT.getNode(RootBB);

1323

1324 auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) {

1326 << TN->getDFSNumOut() << '}';

1327 };

1328

1329

1330

1332 errs() << "DFSIn number for the tree root is not:\n\t";

1333 PrintNodeAndDFSNums(Root);

1334 errs() << '\n';

1336 return false;

1337 }

1338

1339

1340

1341 for (const auto &NodeToTN : DT.DomTreeNodes) {

1344 continue;

1345

1346

1347 if (Node->isLeaf()) {

1348 if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) {

1349 errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t";

1350 PrintNodeAndDFSNums(Node);

1351 errs() << '\n';

1353 return false;

1354 }

1355

1356 continue;

1357 }

1358

1359

1360

1364 });

1365

1366 auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums](

1369

1370 errs() << "Incorrect DFS numbers for:\n\tParent ";

1371 PrintNodeAndDFSNums(Node);

1372

1373 errs() << "\n\tChild ";

1374 PrintNodeAndDFSNums(FirstCh);

1375

1376 if (SecondCh) {

1377 errs() << "\n\tSecond child ";

1378 PrintNodeAndDFSNums(SecondCh);

1379 }

1380

1381 errs() << "\nAll children: ";

1383 PrintNodeAndDFSNums(Ch);

1384 errs() << ", ";

1385 }

1386

1387 errs() << '\n';

1389 };

1390

1391 if (Children.front()->getDFSNumIn() != Node->getDFSNumIn() + 1) {

1392 PrintChildrenError(Children.front(), nullptr);

1393 return false;

1394 }

1395

1396 if (Children.back()->getDFSNumOut() + 1 != Node->getDFSNumOut()) {

1397 PrintChildrenError(Children.back(), nullptr);

1398 return false;

1399 }

1400

1401 for (size_t i = 0, e = Children.size() - 1; i != e; ++i) {

1402 if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) {

1403 PrintChildrenError(Children[i], Children[i + 1]);

1404 return false;

1405 }

1406 }

1407 }

1408

1409 return true;

1410 }

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1429

1430

1431

1432

1433

1434

1435

1436

1437

1438

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1452

1453

1454

1456 for (auto &NodeToTN : DT.DomTreeNodes) {

1458 if (!TN)

1459 continue;

1461 if (!BB || TN->isLeaf())

1462 continue;

1463

1464 LLVM_DEBUG(dbgs() << "Verifying parent property of node "

1468 return From != BB && To != BB;

1469 });

1470

1475 << " is removed!\n";

1477

1478 return false;

1479 }

1480 }

1481

1482 return true;

1483 }

1484

1485

1486

1487

1488

1489

1490

1492 for (auto &NodeToTN : DT.DomTreeNodes) {

1494 if (!TN)

1495 continue;

1497 if (!BB || TN->isLeaf())

1498 continue;

1499

1502 NodePtr BBN = N->getBlock();

1504 return From != BBN && To != BBN;

1505 });

1506

1508 if (S == N) continue;

1509

1513 << " is removed!\n";

1515

1516 return false;

1517 }

1518 }

1519 }

1520 }

1521

1522 return true;

1523 }

1524

1525

1526

1527

1528

1529

1530

1531

1533 DomTreeT FreshTree;

1534 FreshTree.recalculate(*DT.Parent);

1535 const bool Different = DT.compare(FreshTree);

1536

1537 if (Different) {

1538 errs() << (DT.isPostDominator() ? "Post" : "")

1539 << "DominatorTree is different than a freshly computed one!\n"

1540 << "\tCurrent:\n";

1541 DT.print(errs());

1542 errs() << "\n\tFreshly computed tree:\n";

1543 FreshTree.print(errs());

1545 }

1546

1547 return !Different;

1548 }

1549};

1550

1551template

1554}

1555

1556template

1559

1560

1562 Updates, true);

1565}

1566

1567template

1569 typename DomTreeT::NodePtr To) {

1572}

1573

1574template

1576 typename DomTreeT::NodePtr To) {

1579}

1580

1581template

1583 GraphDiff<typename DomTreeT::NodePtr,

1584 DomTreeT::IsPostDominator> &PreViewCFG,

1585 GraphDiff<typename DomTreeT::NodePtr,

1586 DomTreeT::IsPostDominator> *PostViewCFG) {

1588}

1589

1590template

1591bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) {

1593

1594

1595

1597 return false;

1598

1599

1602 return false;

1603

1604

1605 if (VL == DomTreeT::VerificationLevel::Basic ||

1606 VL == DomTreeT::VerificationLevel::Full)

1608 return false;

1609 if (VL == DomTreeT::VerificationLevel::Full)

1611 return false;

1612

1613 return true;

1614}

1615

1616}

1617}

1618

1619#undef DEBUG_TYPE

1620

1621#endif

Unify divergent function exit nodes

BlockVerifier::State From

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

This file defines the DenseSet and SmallDenseSet classes.

This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.

This file defines a set of templates that efficiently compute a dominator tree over a generic graph.

Loop::LoopBounds::Direction Direction

uint64_t IntrinsicInst * II

ppc ctr loops PowerPC CTR Loops Verify

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallPtrSet class.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

Base class for the actual dominator tree node.

iterator_range< iterator > children()

void setIDom(DomTreeNodeBase *NewIDom)

DomTreeNodeBase * getIDom() const

unsigned getDFSNumIn() const

getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.

unsigned getLevel() const

cfg::Update< NodePtr > popUpdateForIncrementalUpdates()

unsigned getNumLegalizedUpdates() const

Implements a dense probed hash-table based set with some number of buckets stored inline.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void reserve(size_type N)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

This class implements an extremely fast bulk output stream that can only output to a stream.

void CalculateWithUpdates(DomTreeT &DT, ArrayRef< typename DomTreeT::UpdateType > Updates)

void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)

void Calculate(DomTreeT &DT)

void ApplyUpdates(DomTreeT &DT, GraphDiff< typename DomTreeT::NodePtr, DomTreeT::IsPostDominator > &PreViewCFG, GraphDiff< typename DomTreeT::NodePtr, DomTreeT::IsPostDominator > *PostViewCFG)

void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

void erase(Container &C, ValueType V)

Wrapper function to remove a value from a container:

void sort(IteratorTy Start, IteratorTy End)

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.

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

BatchUpdateInfo(GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG=nullptr)

const size_t NumLegalized

friend raw_ostream & operator<<(raw_ostream &O, const BlockNamePrinter &BP)

BlockNamePrinter(NodePtr Block)

BlockNamePrinter(TreeNodePtr TN)

SmallVector< unsigned, 4 > ReverseChildren

bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const

std::priority_queue< TreeNodePtr, SmallVector< TreeNodePtr, 8 >, Compare > Bucket

SmallVector< TreeNodePtr, 8 > Affected

SmallDenseSet< TreeNodePtr, 8 > Visited

SemiNCAInfo(BatchUpdatePtr BUI)

static SmallVector< NodePtr, 8 > getChildren(NodePtr N)

static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr NCD, InsertionInfo &II)

static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To)

NodePtr getIDom(NodePtr BB)

InfoRec & getNodeInfo(NodePtr BB)

void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC)

DenseMap< NodePtr, unsigned > NodeOrderMap

static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI)

static SmallVector< NodePtr, 8 > getChildren(NodePtr N, BatchUpdatePtr BUI)

static void ComputeUnreachableDominators(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr Root, const TreeNodePtr Incoming, SmallVectorImpl< std::pair< NodePtr, TreeNodePtr > > &DiscoveredConnectingEdges)

static bool VerifyLevels(const DomTreeT &DT)

decltype(DomTreeT::Roots) RootsT

bool verifyReachability(const DomTreeT &DT)

unsigned eval(unsigned V, unsigned LastLinked, SmallVectorImpl< InfoRec * > &Stack, ArrayRef< InfoRec * > NumToInfo)

static bool IsSameAsFreshTree(const DomTreeT &DT)

static constexpr bool IsPostDom

typename DomTreeT::NodePtr NodePtr

static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG)

typename DomTreeT::UpdateKind UpdateKind

static bool UpdateRootsBeforeInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const TreeNodePtr To)

bool verifySiblingProperty(const DomTreeT &DT)

typename DomTreeT::NodeType NodeT

void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo)

static NodePtr GetEntryNode(const DomTreeT &DT)

static bool AlwaysDescend(NodePtr, NodePtr)

static void UpdateRootsAfterUpdate(DomTreeT &DT, const BatchUpdatePtr BUI)

SmallVector< NodePtr, 64 > NumToNode

unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition, unsigned AttachToNum, const NodeOrderMap *SuccOrder=nullptr)

static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr FromTN, const TreeNodePtr ToTN)

static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI, RootsT &Roots)

static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr TN)

static bool isPermutation(const SmallVectorImpl< NodePtr > &A, const SmallVectorImpl< NodePtr > &B)

static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI)

TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT)

typename DomTreeT::UpdateType UpdateT

static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const TreeNodePtr To)

static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI)

static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const NodePtr To)

static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI)

static bool VerifyDFSNumbers(const DomTreeT &DT)

static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr ToTN)

void attachNewSubtree(DomTreeT &DT, const TreeNodePtr AttachTo)

static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To)

BatchUpdateInfo * BatchUpdates

bool verifyParentProperty(const DomTreeT &DT)

bool verifyRoots(const DomTreeT &DT)

std::conditional_t< GraphHasNodeNumbers< NodePtr >, SmallVector< InfoRec, 64 >, DenseMap< NodePtr, InfoRec > > NodeInfos

Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...