Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:28

0001 //===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines specializations of GraphTraits that allows generic
0010 // algorithms to see a different snapshot of a CFG.
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 // Two booleans are used to define orders in graphs:
0027 // InverseGraph defines when we need to reverse the whole graph and is as such
0028 // also equivalent to applying updates in reverse.
0029 // InverseEdge defines whether we want to change the edges direction. E.g., for
0030 // a non-inversed graph, the children are naturally the successors when
0031 // InverseEdge is false and the predecessors when InverseEdge is true.
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 } // namespace detail
0051 
0052 // GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provides
0053 // a getChildren method to get a Node's children based on the additional updates
0054 // in the snapshot. The current diff treats the CFG as a graph rather than a
0055 // multigraph. Added edges are pruned to be unique, and deleted edges will
0056 // remove all existing edges between two blocks.
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   // By default, it is assumed that, given a CFG and a set of updates, we wish
0066   // to apply these updates as given. If UpdatedAreReverseApplied is set, the
0067   // updates will be applied in reverse: deleted edges are considered re-added
0068   // and inserted edges are considered deleted when returning children.
0069   bool UpdatedAreReverseApplied;
0070 
0071   // Keep the list of legalized updates for a deterministic order of updates
0072   // when using a GraphDiff for incremental updates in the DominatorTree.
0073   // The list is kept in reverse to allow popping from end.
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     // Remove nullptr children for clang.
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     // Remove children present in the CFG but not in the snapshot.
0150     for (auto *Child : It->second.DI[0])
0151       llvm::erase(Res, Child);
0152 
0153     // Add children present in the snapshot for not in the real CFG.
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 } // end namespace llvm
0176 
0177 #endif // LLVM_SUPPORT_CFGDIFF_H