Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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