LLVM 22.0.0git
CFGDiff.h
Go to the documentation of this file.
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
18#include "llvm/ADT/iterator.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
33namespace llvm {
34
35namespace detail {
36template <typename Range>
37auto reverse_if_helper(Range &&R, std::bool_constant<false>) {
38 return std::forward<Range>(R);
39}
40
41template <typename Range>
42auto reverse_if_helper(Range &&R, std::bool_constant<true>) {
43 return llvm::reverse(std::forward<Range>(R));
44}
45
46template <bool B, typename Range> auto reverse_if(Range &&R) {
47 return reverse_if_helper(std::forward<Range>(R), std::bool_constant<B>{});
48}
49} // namespace detail
50
51// GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provides
52// a getChildren method to get a Node's children based on the additional updates
53// in the snapshot. The current diff treats the CFG as a graph rather than a
54// multigraph. Added edges are pruned to be unique, and deleted edges will
55// remove all existing edges between two blocks.
56template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
57 struct DeletesInserts {
59 };
60 using UpdateMapType = SmallDenseMap<NodePtr, DeletesInserts>;
61 UpdateMapType Succ;
62 UpdateMapType Pred;
63
64 // By default, it is assumed that, given a CFG and a set of updates, we wish
65 // to apply these updates as given. If UpdatedAreReverseApplied is set, the
66 // updates will be applied in reverse: deleted edges are considered re-added
67 // and inserted edges are considered deleted when returning children.
68 bool UpdatedAreReverseApplied;
69
70 // Keep the list of legalized updates for a deterministic order of updates
71 // when using a GraphDiff for incremental updates in the DominatorTree.
72 // The list is kept in reverse to allow popping from end.
73 SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
74
75 void printMap(raw_ostream &OS, const UpdateMapType &M) const {
76 StringRef DIText[2] = {"Delete", "Insert"};
77 for (auto Pair : M) {
78 for (unsigned IsInsert = 0; IsInsert <= 1; ++IsInsert) {
79 OS << DIText[IsInsert] << " edges: \n";
80 for (auto Child : Pair.second.DI[IsInsert]) {
81 OS << "(";
82 Pair.first->printAsOperand(OS, false);
83 OS << ", ";
84 Child->printAsOperand(OS, false);
85 OS << ") ";
86 }
87 }
88 }
89 OS << "\n";
90 }
91
92public:
93 GraphDiff() : UpdatedAreReverseApplied(false) {}
95 bool ReverseApplyUpdates = false) {
96 cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
97 for (auto U : LegalizedUpdates) {
98 unsigned IsInsert =
99 (U.getKind() == cfg::UpdateKind::Insert) == !ReverseApplyUpdates;
100 Succ[U.getFrom()].DI[IsInsert].push_back(U.getTo());
101 Pred[U.getTo()].DI[IsInsert].push_back(U.getFrom());
102 }
103 UpdatedAreReverseApplied = ReverseApplyUpdates;
104 }
105
106 auto getLegalizedUpdates() const {
107 return make_range(LegalizedUpdates.begin(), LegalizedUpdates.end());
108 }
109
110 unsigned getNumLegalizedUpdates() const { return LegalizedUpdates.size(); }
111
113 assert(!LegalizedUpdates.empty() && "No updates to apply!");
114 auto U = LegalizedUpdates.pop_back_val();
115 unsigned IsInsert =
116 (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
117 auto &SuccDIList = Succ[U.getFrom()];
118 auto &SuccList = SuccDIList.DI[IsInsert];
119 assert(SuccList.back() == U.getTo());
120 SuccList.pop_back();
121 if (SuccList.empty() && SuccDIList.DI[!IsInsert].empty())
122 Succ.erase(U.getFrom());
123
124 auto &PredDIList = Pred[U.getTo()];
125 auto &PredList = PredDIList.DI[IsInsert];
126 assert(PredList.back() == U.getFrom());
127 PredList.pop_back();
128 if (PredList.empty() && PredDIList.DI[!IsInsert].empty())
129 Pred.erase(U.getTo());
130 return U;
131 }
132
134 template <bool InverseEdge> VectRet getChildren(NodePtr N) const {
135 using DirectedNodeT =
136 std::conditional_t<InverseEdge, Inverse<NodePtr>, NodePtr>;
137 auto R = children<DirectedNodeT>(N);
139
140 // Remove nullptr children for clang.
141 llvm::erase(Res, nullptr);
142
143 auto &Children = (InverseEdge != InverseGraph) ? Pred : Succ;
144 auto It = Children.find(N);
145 if (It == Children.end())
146 return Res;
147
148 // Remove children present in the CFG but not in the snapshot.
149 for (auto *Child : It->second.DI[0])
150 llvm::erase(Res, Child);
151
152 // Add children present in the snapshot for not in the real CFG.
153 auto &AddedChildren = It->second.DI[1];
154 llvm::append_range(Res, AddedChildren);
155
156 return Res;
157 }
158
159 void print(raw_ostream &OS) const {
160 OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
161 "===== (Note: notion of children/inverse_children depends on "
162 "the direction of edges and the graph.)\n";
163 OS << "Children to delete/insert:\n\t";
164 printMap(OS, Succ);
165 OS << "Inverse_children to delete/insert:\n\t";
166 printMap(OS, Pred);
167 OS << "\n";
168 }
169
170#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
171 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
172#endif
173};
174} // end namespace llvm
175
176#endif // LLVM_SUPPORT_CFGDIFF_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
auto getLegalizedUpdates() const
Definition CFGDiff.h:106
SmallVector< MachineBasicBlock *, 8 > VectRet
Definition CFGDiff.h:133
void print(raw_ostream &OS) const
Definition CFGDiff.h:159
LLVM_DUMP_METHOD void dump() const
Definition CFGDiff.h:171
VectRet getChildren(NodePtr N) const
Definition CFGDiff.h:134
GraphDiff(ArrayRef< cfg::Update< NodePtr > > Updates, bool ReverseApplyUpdates=false)
Definition CFGDiff.h:94
cfg::Update< NodePtr > popUpdateForIncrementalUpdates()
Definition CFGDiff.h:112
unsigned getNumLegalizedUpdates() const
Definition CFGDiff.h:110
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
void LegalizeUpdates(ArrayRef< Update< NodePtr > > AllUpdates, SmallVectorImpl< Update< NodePtr > > &Result, bool InverseGraph, bool ReverseResultOrder=false)
Definition CFGUpdate.h:63
These are wrappers over isa* function that allow them to be used in generic algorithms such as llvm:a...
Definition ADL.h:123
auto reverse_if(Range &&R)
Definition CFGDiff.h:46
auto reverse_if_helper(Range &&R, std::bool_constant< false >)
Definition CFGDiff.h:37
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2118
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition STLExtras.h:2110
auto reverse(ContainerTy &&C)
Definition STLExtras.h:400
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
#define N