File indexing completed on 2026-05-10 08:44:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_CFGDIFF_H
0015 #define LLVM_SUPPORT_CFGDIFF_H
0016
0017 #include "llvm/ADT/GraphTraits.h"
0018 #include "llvm/ADT/iterator.h"
0019 #include "llvm/ADT/iterator_range.h"
0020 #include "llvm/Support/CFGUpdate.h"
0021 #include "llvm/Support/type_traits.h"
0022 #include <cassert>
0023 #include <cstddef>
0024 #include <iterator>
0025
0026
0027
0028
0029
0030
0031
0032
0033 namespace llvm {
0034
0035 namespace detail {
0036 template <typename Range>
0037 auto reverse_if_helper(Range &&R, std::integral_constant<bool, false>) {
0038 return std::forward<Range>(R);
0039 }
0040
0041 template <typename Range>
0042 auto reverse_if_helper(Range &&R, std::integral_constant<bool, true>) {
0043 return llvm::reverse(std::forward<Range>(R));
0044 }
0045
0046 template <bool B, typename Range> auto reverse_if(Range &&R) {
0047 return reverse_if_helper(std::forward<Range>(R),
0048 std::integral_constant<bool, B>{});
0049 }
0050 }
0051
0052
0053
0054
0055
0056
0057 template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
0058 struct DeletesInserts {
0059 SmallVector<NodePtr, 2> DI[2];
0060 };
0061 using UpdateMapType = SmallDenseMap<NodePtr, DeletesInserts>;
0062 UpdateMapType Succ;
0063 UpdateMapType Pred;
0064
0065
0066
0067
0068
0069 bool UpdatedAreReverseApplied;
0070
0071
0072
0073
0074 SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
0075
0076 void printMap(raw_ostream &OS, const UpdateMapType &M) const {
0077 StringRef DIText[2] = {"Delete", "Insert"};
0078 for (auto Pair : M) {
0079 for (unsigned IsInsert = 0; IsInsert <= 1; ++IsInsert) {
0080 OS << DIText[IsInsert] << " edges: \n";
0081 for (auto Child : Pair.second.DI[IsInsert]) {
0082 OS << "(";
0083 Pair.first->printAsOperand(OS, false);
0084 OS << ", ";
0085 Child->printAsOperand(OS, false);
0086 OS << ") ";
0087 }
0088 }
0089 }
0090 OS << "\n";
0091 }
0092
0093 public:
0094 GraphDiff() : UpdatedAreReverseApplied(false) {}
0095 GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates,
0096 bool ReverseApplyUpdates = false) {
0097 cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
0098 for (auto U : LegalizedUpdates) {
0099 unsigned IsInsert =
0100 (U.getKind() == cfg::UpdateKind::Insert) == !ReverseApplyUpdates;
0101 Succ[U.getFrom()].DI[IsInsert].push_back(U.getTo());
0102 Pred[U.getTo()].DI[IsInsert].push_back(U.getFrom());
0103 }
0104 UpdatedAreReverseApplied = ReverseApplyUpdates;
0105 }
0106
0107 auto getLegalizedUpdates() const {
0108 return make_range(LegalizedUpdates.begin(), LegalizedUpdates.end());
0109 }
0110
0111 unsigned getNumLegalizedUpdates() const { return LegalizedUpdates.size(); }
0112
0113 cfg::Update<NodePtr> popUpdateForIncrementalUpdates() {
0114 assert(!LegalizedUpdates.empty() && "No updates to apply!");
0115 auto U = LegalizedUpdates.pop_back_val();
0116 unsigned IsInsert =
0117 (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
0118 auto &SuccDIList = Succ[U.getFrom()];
0119 auto &SuccList = SuccDIList.DI[IsInsert];
0120 assert(SuccList.back() == U.getTo());
0121 SuccList.pop_back();
0122 if (SuccList.empty() && SuccDIList.DI[!IsInsert].empty())
0123 Succ.erase(U.getFrom());
0124
0125 auto &PredDIList = Pred[U.getTo()];
0126 auto &PredList = PredDIList.DI[IsInsert];
0127 assert(PredList.back() == U.getFrom());
0128 PredList.pop_back();
0129 if (PredList.empty() && PredDIList.DI[!IsInsert].empty())
0130 Pred.erase(U.getTo());
0131 return U;
0132 }
0133
0134 using VectRet = SmallVector<NodePtr, 8>;
0135 template <bool InverseEdge> VectRet getChildren(NodePtr N) const {
0136 using DirectedNodeT =
0137 std::conditional_t<InverseEdge, Inverse<NodePtr>, NodePtr>;
0138 auto R = children<DirectedNodeT>(N);
0139 VectRet Res = VectRet(detail::reverse_if<!InverseEdge>(R));
0140
0141
0142 llvm::erase(Res, nullptr);
0143
0144 auto &Children = (InverseEdge != InverseGraph) ? Pred : Succ;
0145 auto It = Children.find(N);
0146 if (It == Children.end())
0147 return Res;
0148
0149
0150 for (auto *Child : It->second.DI[0])
0151 llvm::erase(Res, Child);
0152
0153
0154 auto &AddedChildren = It->second.DI[1];
0155 llvm::append_range(Res, AddedChildren);
0156
0157 return Res;
0158 }
0159
0160 void print(raw_ostream &OS) const {
0161 OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
0162 "===== (Note: notion of children/inverse_children depends on "
0163 "the direction of edges and the graph.)\n";
0164 OS << "Children to delete/insert:\n\t";
0165 printMap(OS, Succ);
0166 OS << "Inverse_children to delete/insert:\n\t";
0167 printMap(OS, Pred);
0168 OS << "\n";
0169 }
0170
0171 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0172 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
0173 #endif
0174 };
0175 }
0176
0177 #endif