- //===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file defines a CFG Edge Update: Insert or Delete, and two Nodes as the 
- // Edge ends. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_SUPPORT_CFGUPDATE_H 
- #define LLVM_SUPPORT_CFGUPDATE_H 
-   
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ADT/PointerIntPair.h" 
- #include "llvm/Support/Compiler.h" 
- #include "llvm/Support/Debug.h" 
- #include "llvm/Support/raw_ostream.h" 
-   
- namespace llvm { 
- namespace cfg { 
- enum class UpdateKind : unsigned char { Insert, Delete }; 
-   
- template <typename NodePtr> class Update { 
-   using NodeKindPair = PointerIntPair<NodePtr, 1, UpdateKind>; 
-   NodePtr From; 
-   NodeKindPair ToAndKind; 
-   
- public: 
-   Update(UpdateKind Kind, NodePtr From, NodePtr To) 
-       : From(From), ToAndKind(To, Kind) {} 
-   
-   UpdateKind getKind() const { return ToAndKind.getInt(); } 
-   NodePtr getFrom() const { return From; } 
-   NodePtr getTo() const { return ToAndKind.getPointer(); } 
-   bool operator==(const Update &RHS) const { 
-     return From == RHS.From && ToAndKind == RHS.ToAndKind; 
-   } 
-   
-   void print(raw_ostream &OS) const { 
-     OS << (getKind() == UpdateKind::Insert ? "Insert " : "Delete "); 
-     getFrom()->printAsOperand(OS, false); 
-     OS << " -> "; 
-     getTo()->printAsOperand(OS, false); 
-   } 
-   
- #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 
-   LLVM_DUMP_METHOD void dump() const { print(dbgs()); } 
- #endif 
- }; 
-   
- // LegalizeUpdates function simplifies updates assuming a graph structure. 
- // This function serves double purpose: 
- // a) It removes redundant updates, which makes it easier to reverse-apply 
- //    them when traversing CFG. 
- // b) It optimizes away updates that cancel each other out, as the end result 
- //    is the same. 
- template <typename NodePtr> 
- void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates, 
-                      SmallVectorImpl<Update<NodePtr>> &Result, 
-                      bool InverseGraph, bool ReverseResultOrder = false) { 
-   // Count the total number of inserions of each edge. 
-   // Each insertion adds 1 and deletion subtracts 1. The end number should be 
-   // one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence 
-   // of updates contains multiple updates of the same kind and we assert for 
-   // that case. 
-   SmallDenseMap<std::pair<NodePtr, NodePtr>, int, 4> Operations; 
-   Operations.reserve(AllUpdates.size()); 
-   
-   for (const auto &U : AllUpdates) { 
-     NodePtr From = U.getFrom(); 
-     NodePtr To = U.getTo(); 
-     if (InverseGraph) 
-       std::swap(From, To); // Reverse edge for postdominators. 
-   
-     Operations[{From, To}] += (U.getKind() == UpdateKind::Insert ? 1 : -1); 
-   } 
-   
-   Result.clear(); 
-   Result.reserve(Operations.size()); 
-   for (auto &Op : Operations) { 
-     const int NumInsertions = Op.second; 
-     assert(std::abs(NumInsertions) <= 1 && "Unbalanced operations!"); 
-     if (NumInsertions == 0) 
-       continue; 
-     const UpdateKind UK = 
-         NumInsertions > 0 ? UpdateKind::Insert : UpdateKind::Delete; 
-     Result.push_back({UK, Op.first.first, Op.first.second}); 
-   } 
-   
-   // Make the order consistent by not relying on pointer values within the 
-   // set. Reuse the old Operations map. 
-   // In the future, we should sort by something else to minimize the amount 
-   // of work needed to perform the series of updates. 
-   for (size_t i = 0, e = AllUpdates.size(); i != e; ++i) { 
-     const auto &U = AllUpdates[i]; 
-     if (!InverseGraph) 
-       Operations[{U.getFrom(), U.getTo()}] = int(i); 
-     else 
-       Operations[{U.getTo(), U.getFrom()}] = int(i); 
-   } 
-   
-   llvm::sort(Result, [&](const Update<NodePtr> &A, const Update<NodePtr> &B) { 
-     const auto &OpA = Operations[{A.getFrom(), A.getTo()}]; 
-     const auto &OpB = Operations[{B.getFrom(), B.getTo()}]; 
-     return ReverseResultOrder ? OpA < OpB : OpA > OpB; 
-   }); 
- } 
-   
- } // end namespace cfg 
- } // end namespace llvm 
-   
- #endif // LLVM_SUPPORT_CFGUPDATE_H 
-