CFGDiff.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines specializations of GraphTraits that allows generic
  15. // algorithms to see a different snapshot of a CFG.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_SUPPORT_CFGDIFF_H
  19. #define LLVM_SUPPORT_CFGDIFF_H
  20. #include "llvm/ADT/GraphTraits.h"
  21. #include "llvm/ADT/iterator.h"
  22. #include "llvm/ADT/iterator_range.h"
  23. #include "llvm/Support/CFGUpdate.h"
  24. #include "llvm/Support/type_traits.h"
  25. #include <cassert>
  26. #include <cstddef>
  27. #include <iterator>
  28. // Two booleans are used to define orders in graphs:
  29. // InverseGraph defines when we need to reverse the whole graph and is as such
  30. // also equivalent to applying updates in reverse.
  31. // InverseEdge defines whether we want to change the edges direction. E.g., for
  32. // a non-inversed graph, the children are naturally the successors when
  33. // InverseEdge is false and the predecessors when InverseEdge is true.
  34. namespace llvm {
  35. namespace detail {
  36. template <typename Range>
  37. auto reverse_if_helper(Range &&R, std::integral_constant<bool, false>) {
  38. return std::forward<Range>(R);
  39. }
  40. template <typename Range>
  41. auto reverse_if_helper(Range &&R, std::integral_constant<bool, true>) {
  42. return llvm::reverse(std::forward<Range>(R));
  43. }
  44. template <bool B, typename Range> auto reverse_if(Range &&R) {
  45. return reverse_if_helper(std::forward<Range>(R),
  46. std::integral_constant<bool, B>{});
  47. }
  48. } // namespace detail
  49. // GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provides
  50. // a getChildren method to get a Node's children based on the additional updates
  51. // in the snapshot. The current diff treats the CFG as a graph rather than a
  52. // multigraph. Added edges are pruned to be unique, and deleted edges will
  53. // remove all existing edges between two blocks.
  54. template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
  55. struct DeletesInserts {
  56. SmallVector<NodePtr, 2> DI[2];
  57. };
  58. using UpdateMapType = SmallDenseMap<NodePtr, DeletesInserts>;
  59. UpdateMapType Succ;
  60. UpdateMapType Pred;
  61. // By default, it is assumed that, given a CFG and a set of updates, we wish
  62. // to apply these updates as given. If UpdatedAreReverseApplied is set, the
  63. // updates will be applied in reverse: deleted edges are considered re-added
  64. // and inserted edges are considered deleted when returning children.
  65. bool UpdatedAreReverseApplied;
  66. // Keep the list of legalized updates for a deterministic order of updates
  67. // when using a GraphDiff for incremental updates in the DominatorTree.
  68. // The list is kept in reverse to allow popping from end.
  69. SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
  70. void printMap(raw_ostream &OS, const UpdateMapType &M) const {
  71. StringRef DIText[2] = {"Delete", "Insert"};
  72. for (auto Pair : M) {
  73. for (unsigned IsInsert = 0; IsInsert <= 1; ++IsInsert) {
  74. OS << DIText[IsInsert] << " edges: \n";
  75. for (auto Child : Pair.second.DI[IsInsert]) {
  76. OS << "(";
  77. Pair.first->printAsOperand(OS, false);
  78. OS << ", ";
  79. Child->printAsOperand(OS, false);
  80. OS << ") ";
  81. }
  82. }
  83. }
  84. OS << "\n";
  85. }
  86. public:
  87. GraphDiff() : UpdatedAreReverseApplied(false) {}
  88. GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates,
  89. bool ReverseApplyUpdates = false) {
  90. cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
  91. for (auto U : LegalizedUpdates) {
  92. unsigned IsInsert =
  93. (U.getKind() == cfg::UpdateKind::Insert) == !ReverseApplyUpdates;
  94. Succ[U.getFrom()].DI[IsInsert].push_back(U.getTo());
  95. Pred[U.getTo()].DI[IsInsert].push_back(U.getFrom());
  96. }
  97. UpdatedAreReverseApplied = ReverseApplyUpdates;
  98. }
  99. auto getLegalizedUpdates() const {
  100. return make_range(LegalizedUpdates.begin(), LegalizedUpdates.end());
  101. }
  102. unsigned getNumLegalizedUpdates() const { return LegalizedUpdates.size(); }
  103. cfg::Update<NodePtr> popUpdateForIncrementalUpdates() {
  104. assert(!LegalizedUpdates.empty() && "No updates to apply!");
  105. auto U = LegalizedUpdates.pop_back_val();
  106. unsigned IsInsert =
  107. (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
  108. auto &SuccDIList = Succ[U.getFrom()];
  109. auto &SuccList = SuccDIList.DI[IsInsert];
  110. assert(SuccList.back() == U.getTo());
  111. SuccList.pop_back();
  112. if (SuccList.empty() && SuccDIList.DI[!IsInsert].empty())
  113. Succ.erase(U.getFrom());
  114. auto &PredDIList = Pred[U.getTo()];
  115. auto &PredList = PredDIList.DI[IsInsert];
  116. assert(PredList.back() == U.getFrom());
  117. PredList.pop_back();
  118. if (PredList.empty() && PredDIList.DI[!IsInsert].empty())
  119. Pred.erase(U.getTo());
  120. return U;
  121. }
  122. using VectRet = SmallVector<NodePtr, 8>;
  123. template <bool InverseEdge> VectRet getChildren(NodePtr N) const {
  124. using DirectedNodeT =
  125. std::conditional_t<InverseEdge, Inverse<NodePtr>, NodePtr>;
  126. auto R = children<DirectedNodeT>(N);
  127. VectRet Res = VectRet(detail::reverse_if<!InverseEdge>(R));
  128. // Remove nullptr children for clang.
  129. llvm::erase_value(Res, nullptr);
  130. auto &Children = (InverseEdge != InverseGraph) ? Pred : Succ;
  131. auto It = Children.find(N);
  132. if (It == Children.end())
  133. return Res;
  134. // Remove children present in the CFG but not in the snapshot.
  135. for (auto *Child : It->second.DI[0])
  136. llvm::erase_value(Res, Child);
  137. // Add children present in the snapshot for not in the real CFG.
  138. auto &AddedChildren = It->second.DI[1];
  139. llvm::append_range(Res, AddedChildren);
  140. return Res;
  141. }
  142. void print(raw_ostream &OS) const {
  143. OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
  144. "===== (Note: notion of children/inverse_children depends on "
  145. "the direction of edges and the graph.)\n";
  146. OS << "Children to delete/insert:\n\t";
  147. printMap(OS, Succ);
  148. OS << "Inverse_children to delete/insert:\n\t";
  149. printMap(OS, Pred);
  150. OS << "\n";
  151. }
  152. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  153. LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
  154. #endif
  155. };
  156. } // end namespace llvm
  157. #endif // LLVM_SUPPORT_CFGDIFF_H
  158. #ifdef __GNUC__
  159. #pragma GCC diagnostic pop
  160. #endif