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_IR_CFGDIFF_H 15 #define LLVM_IR_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/IR/BasicBlock.h" 21 #include "llvm/IR/CFG.h" 22 #include "llvm/Support/CFGUpdate.h" 23 #include "llvm/Support/type_traits.h" 24 #include <cassert> 25 #include <cstddef> 26 #include <iterator> 27 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 35 // We define two base clases that call into GraphDiff, one for successors 36 // (CFGSuccessors), where InverseEdge is false, and one for predecessors 37 // (CFGPredecessors), where InverseEdge is true. 38 // FIXME: Further refactoring may merge the two base classes into a single one 39 // templated / parametrized on using succ_iterator/pred_iterator and false/true 40 // for the InverseEdge. 41 42 // CFGViewSuccessors and CFGViewPredecessors, both can be parametrized to 43 // consider the graph inverted or not (i.e. InverseGraph). Successors 44 // implicitly has InverseEdge = false and Predecessors implicitly has 45 // InverseEdge = true (see calls to GraphDiff methods in there). The GraphTraits 46 // instantiations that follow define the value of InverseGraph. 47 48 // GraphTraits instantiations: 49 // - GraphDiff<BasicBlock *> is equivalent to InverseGraph = false 50 // - GraphDiff<Inverse<BasicBlock *>> is equivalent to InverseGraph = true 51 // - second pair item is BasicBlock *, then InverseEdge = false (so it inherits 52 // from CFGViewSuccessors). 53 // - second pair item is Inverse<BasicBlock *>, then InverseEdge = true (so it 54 // inherits from CFGViewPredecessors). 55 56 // The 4 GraphTraits are as follows: 57 // 1. std::pair<const GraphDiff<BasicBlock *> *, BasicBlock *>> : 58 // CFGViewSuccessors<false> 59 // Regular CFG, children means successors, InverseGraph = false, 60 // InverseEdge = false. 61 // 2. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, BasicBlock *>> : 62 // CFGViewSuccessors<true> 63 // Reverse the graph, get successors but reverse-apply updates, 64 // InverseGraph = true, InverseEdge = false. 65 // 3. std::pair<const GraphDiff<BasicBlock *> *, Inverse<BasicBlock *>>> : 66 // CFGViewPredecessors<false> 67 // Regular CFG, reverse edges, so children mean predecessors, 68 // InverseGraph = false, InverseEdge = true. 69 // 4. std::pair<const GraphDiff<Inverse<BasicBlock *>> *, Inverse<BasicBlock *>> 70 // : CFGViewPredecessors<true> 71 // Reverse the graph and the edges, InverseGraph = true, InverseEdge = true. 72 73 namespace llvm { 74 75 // GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provide 76 // utilities to skip edges marked as deleted and return a set of edges marked as 77 // newly inserted. The current diff treats the CFG as a graph rather than a 78 // multigraph. Added edges are pruned to be unique, and deleted edges will 79 // remove all existing edges between two blocks. 80 template <typename NodePtr, bool InverseGraph = false> class GraphDiff { 81 using UpdateMapType = SmallDenseMap<NodePtr, SmallVector<NodePtr, 2>>; 82 UpdateMapType SuccInsert; 83 UpdateMapType SuccDelete; 84 UpdateMapType PredInsert; 85 UpdateMapType PredDelete; 86 // Using a singleton empty vector for all BasicBlock requests with no 87 // children. 88 SmallVector<NodePtr, 1> Empty; 89 printMap(raw_ostream & OS,const UpdateMapType & M)90 void printMap(raw_ostream &OS, const UpdateMapType &M) const { 91 for (auto Pair : M) 92 for (auto Child : Pair.second) { 93 OS << "("; 94 Pair.first->printAsOperand(OS, false); 95 OS << ", "; 96 Child->printAsOperand(OS, false); 97 OS << ") "; 98 } 99 OS << "\n"; 100 } 101 102 public: GraphDiff()103 GraphDiff() {} GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates)104 GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates) { 105 SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates; 106 cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph); 107 for (auto U : LegalizedUpdates) { 108 if (U.getKind() == cfg::UpdateKind::Insert) { 109 SuccInsert[U.getFrom()].push_back(U.getTo()); 110 PredInsert[U.getTo()].push_back(U.getFrom()); 111 } else { 112 SuccDelete[U.getFrom()].push_back(U.getTo()); 113 PredDelete[U.getTo()].push_back(U.getFrom()); 114 } 115 } 116 } 117 ignoreChild(const NodePtr BB,NodePtr EdgeEnd,bool InverseEdge)118 bool ignoreChild(const NodePtr BB, NodePtr EdgeEnd, bool InverseEdge) const { 119 auto &DeleteChildren = 120 (InverseEdge != InverseGraph) ? PredDelete : SuccDelete; 121 auto It = DeleteChildren.find(BB); 122 if (It == DeleteChildren.end()) 123 return false; 124 auto &EdgesForBB = It->second; 125 return llvm::find(EdgesForBB, EdgeEnd) != EdgesForBB.end(); 126 } 127 128 iterator_range<typename SmallVectorImpl<NodePtr>::const_iterator> getAddedChildren(const NodePtr BB,bool InverseEdge)129 getAddedChildren(const NodePtr BB, bool InverseEdge) const { 130 auto &InsertChildren = 131 (InverseEdge != InverseGraph) ? PredInsert : SuccInsert; 132 auto It = InsertChildren.find(BB); 133 if (It == InsertChildren.end()) 134 return make_range(Empty.begin(), Empty.end()); 135 return make_range(It->second.begin(), It->second.end()); 136 } 137 print(raw_ostream & OS)138 void print(raw_ostream &OS) const { 139 OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n" 140 "===== (Note: notion of children/inverse_children depends on " 141 "the direction of edges and the graph.)\n"; 142 OS << "Children to insert:\n\t"; 143 printMap(OS, SuccInsert); 144 OS << "Children to delete:\n\t"; 145 printMap(OS, SuccDelete); 146 OS << "Inverse_children to insert:\n\t"; 147 printMap(OS, PredInsert); 148 OS << "Inverse_children to delete:\n\t"; 149 printMap(OS, PredDelete); 150 OS << "\n"; 151 } 152 153 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()154 LLVM_DUMP_METHOD void dump() const { print(dbgs()); } 155 #endif 156 }; 157 158 template <bool InverseGraph = false> struct CFGViewSuccessors { 159 using DataRef = const GraphDiff<BasicBlock *, InverseGraph> *; 160 using NodeRef = std::pair<DataRef, BasicBlock *>; 161 162 using ExistingChildIterator = 163 WrappedPairNodeDataIterator<succ_iterator, NodeRef, DataRef>; 164 struct DeletedEdgesFilter { 165 BasicBlock *BB; DeletedEdgesFilterCFGViewSuccessors::DeletedEdgesFilter166 DeletedEdgesFilter(BasicBlock *BB) : BB(BB){}; operatorCFGViewSuccessors::DeletedEdgesFilter167 bool operator()(NodeRef N) const { 168 return !N.first->ignoreChild(BB, N.second, false); 169 } 170 }; 171 using FilterExistingChildrenIterator = 172 filter_iterator<ExistingChildIterator, DeletedEdgesFilter>; 173 174 using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator; 175 using AddNewChildrenIterator = 176 WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>; 177 using ChildIteratorType = 178 concat_iterator<NodeRef, FilterExistingChildrenIterator, 179 AddNewChildrenIterator>; 180 child_beginCFGViewSuccessors181 static ChildIteratorType child_begin(NodeRef N) { 182 auto InsertVec = N.first->getAddedChildren(N.second, false); 183 // filter iterator init: 184 auto firstit = make_filter_range( 185 make_range<ExistingChildIterator>({succ_begin(N.second), N.first}, 186 {succ_end(N.second), N.first}), 187 DeletedEdgesFilter(N.second)); 188 // new inserts iterator init: 189 auto secondit = make_range<AddNewChildrenIterator>( 190 {InsertVec.begin(), N.first}, {InsertVec.end(), N.first}); 191 192 return concat_iterator<NodeRef, FilterExistingChildrenIterator, 193 AddNewChildrenIterator>(firstit, secondit); 194 } 195 child_endCFGViewSuccessors196 static ChildIteratorType child_end(NodeRef N) { 197 auto InsertVec = N.first->getAddedChildren(N.second, false); 198 // filter iterator init: 199 auto firstit = make_filter_range( 200 make_range<ExistingChildIterator>({succ_end(N.second), N.first}, 201 {succ_end(N.second), N.first}), 202 DeletedEdgesFilter(N.second)); 203 // new inserts iterator init: 204 auto secondit = make_range<AddNewChildrenIterator>( 205 {InsertVec.end(), N.first}, {InsertVec.end(), N.first}); 206 207 return concat_iterator<NodeRef, FilterExistingChildrenIterator, 208 AddNewChildrenIterator>(firstit, secondit); 209 } 210 }; 211 212 template <bool InverseGraph = false> struct CFGViewPredecessors { 213 using DataRef = const GraphDiff<BasicBlock *, InverseGraph> *; 214 using NodeRef = std::pair<DataRef, BasicBlock *>; 215 216 using ExistingChildIterator = 217 WrappedPairNodeDataIterator<pred_iterator, NodeRef, DataRef>; 218 struct DeletedEdgesFilter { 219 BasicBlock *BB; DeletedEdgesFilterCFGViewPredecessors::DeletedEdgesFilter220 DeletedEdgesFilter(BasicBlock *BB) : BB(BB){}; operatorCFGViewPredecessors::DeletedEdgesFilter221 bool operator()(NodeRef N) const { 222 return !N.first->ignoreChild(BB, N.second, true); 223 } 224 }; 225 using FilterExistingChildrenIterator = 226 filter_iterator<ExistingChildIterator, DeletedEdgesFilter>; 227 228 using vec_iterator = SmallVectorImpl<BasicBlock *>::const_iterator; 229 using AddNewChildrenIterator = 230 WrappedPairNodeDataIterator<vec_iterator, NodeRef, DataRef>; 231 using ChildIteratorType = 232 concat_iterator<NodeRef, FilterExistingChildrenIterator, 233 AddNewChildrenIterator>; 234 child_beginCFGViewPredecessors235 static ChildIteratorType child_begin(NodeRef N) { 236 auto InsertVec = N.first->getAddedChildren(N.second, true); 237 // filter iterator init: 238 auto firstit = make_filter_range( 239 make_range<ExistingChildIterator>({pred_begin(N.second), N.first}, 240 {pred_end(N.second), N.first}), 241 DeletedEdgesFilter(N.second)); 242 // new inserts iterator init: 243 auto secondit = make_range<AddNewChildrenIterator>( 244 {InsertVec.begin(), N.first}, {InsertVec.end(), N.first}); 245 246 return concat_iterator<NodeRef, FilterExistingChildrenIterator, 247 AddNewChildrenIterator>(firstit, secondit); 248 } 249 child_endCFGViewPredecessors250 static ChildIteratorType child_end(NodeRef N) { 251 auto InsertVec = N.first->getAddedChildren(N.second, true); 252 // filter iterator init: 253 auto firstit = make_filter_range( 254 make_range<ExistingChildIterator>({pred_end(N.second), N.first}, 255 {pred_end(N.second), N.first}), 256 DeletedEdgesFilter(N.second)); 257 // new inserts iterator init: 258 auto secondit = make_range<AddNewChildrenIterator>( 259 {InsertVec.end(), N.first}, {InsertVec.end(), N.first}); 260 261 return concat_iterator<NodeRef, FilterExistingChildrenIterator, 262 AddNewChildrenIterator>(firstit, secondit); 263 } 264 }; 265 266 template <> 267 struct GraphTraits< 268 std::pair<const GraphDiff<BasicBlock *, false> *, BasicBlock *>> 269 : CFGViewSuccessors<false> {}; 270 template <> 271 struct GraphTraits< 272 std::pair<const GraphDiff<BasicBlock *, true> *, BasicBlock *>> 273 : CFGViewSuccessors<true> {}; 274 template <> 275 struct GraphTraits< 276 std::pair<const GraphDiff<BasicBlock *, false> *, Inverse<BasicBlock *>>> 277 : CFGViewPredecessors<false> {}; 278 template <> 279 struct GraphTraits< 280 std::pair<const GraphDiff<BasicBlock *, true> *, Inverse<BasicBlock *>>> 281 : CFGViewPredecessors<true> {}; 282 } // end namespace llvm 283 284 #endif // LLVM_IR_CFGDIFF_H 285