|
|
|||
File indexing completed on 2026-05-10 08:43:12
0001 //===- GenericDomTreeUpdater.h ----------------------------------*- 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 the GenericDomTreeUpdater class, which provides a uniform 0010 // way to update dominator tree related data structures. 0011 // 0012 //===----------------------------------------------------------------------===// 0013 0014 #ifndef LLVM_ANALYSIS_GENERICDOMTREEUPDATER_H 0015 #define LLVM_ANALYSIS_GENERICDOMTREEUPDATER_H 0016 0017 #include "llvm/ADT/ArrayRef.h" 0018 #include "llvm/ADT/SmallSet.h" 0019 #include "llvm/Support/Compiler.h" 0020 0021 namespace llvm { 0022 0023 template <typename DerivedT, typename DomTreeT, typename PostDomTreeT> 0024 class GenericDomTreeUpdater { 0025 DerivedT &derived() { return *static_cast<DerivedT *>(this); } 0026 const DerivedT &derived() const { 0027 return *static_cast<const DerivedT *>(this); 0028 } 0029 0030 public: 0031 enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 }; 0032 using BasicBlockT = typename DomTreeT::NodeType; 0033 using UpdateT = typename DomTreeT::UpdateType; 0034 0035 explicit GenericDomTreeUpdater(UpdateStrategy Strategy_) 0036 : Strategy(Strategy_) {} 0037 GenericDomTreeUpdater(DomTreeT &DT_, UpdateStrategy Strategy_) 0038 : DT(&DT_), Strategy(Strategy_) {} 0039 GenericDomTreeUpdater(DomTreeT *DT_, UpdateStrategy Strategy_) 0040 : DT(DT_), Strategy(Strategy_) {} 0041 GenericDomTreeUpdater(PostDomTreeT &PDT_, UpdateStrategy Strategy_) 0042 : PDT(&PDT_), Strategy(Strategy_) {} 0043 GenericDomTreeUpdater(PostDomTreeT *PDT_, UpdateStrategy Strategy_) 0044 : PDT(PDT_), Strategy(Strategy_) {} 0045 GenericDomTreeUpdater(DomTreeT &DT_, PostDomTreeT &PDT_, 0046 UpdateStrategy Strategy_) 0047 : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {} 0048 GenericDomTreeUpdater(DomTreeT *DT_, PostDomTreeT *PDT_, 0049 UpdateStrategy Strategy_) 0050 : DT(DT_), PDT(PDT_), Strategy(Strategy_) {} 0051 0052 ~GenericDomTreeUpdater() { 0053 // We cannot call into derived() here as it will already be destroyed. 0054 assert(!hasPendingUpdates() && 0055 "Pending updates were not flushed by derived class."); 0056 } 0057 0058 /// Returns true if the current strategy is Lazy. 0059 bool isLazy() const { return Strategy == UpdateStrategy::Lazy; } 0060 0061 /// Returns true if the current strategy is Eager. 0062 bool isEager() const { return Strategy == UpdateStrategy::Eager; } 0063 0064 /// Returns true if it holds a DomTreeT. 0065 bool hasDomTree() const { return DT != nullptr; } 0066 0067 /// Returns true if it holds a PostDomTreeT. 0068 bool hasPostDomTree() const { return PDT != nullptr; } 0069 0070 /// Returns true if there is BasicBlockT awaiting deletion. 0071 /// The deletion will only happen until a flush event and 0072 /// all available trees are up-to-date. 0073 /// Returns false under Eager UpdateStrategy. 0074 bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); } 0075 0076 /// Returns true if DelBB is awaiting deletion. 0077 /// Returns false under Eager UpdateStrategy. 0078 bool isBBPendingDeletion(BasicBlockT *DelBB) const { 0079 if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty()) 0080 return false; 0081 return DeletedBBs.contains(DelBB); 0082 } 0083 0084 /// Returns true if either of DT or PDT is valid and the tree has at 0085 /// least one update pending. If DT or PDT is nullptr it is treated 0086 /// as having no pending updates. This function does not check 0087 /// whether there is MachineBasicBlock awaiting deletion. 0088 /// Returns false under Eager UpdateStrategy. 0089 bool hasPendingUpdates() const { 0090 return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates(); 0091 } 0092 0093 /// Returns true if there are DomTreeT updates queued. 0094 /// Returns false under Eager UpdateStrategy or DT is nullptr. 0095 bool hasPendingDomTreeUpdates() const { 0096 if (!DT) 0097 return false; 0098 return PendUpdates.size() != PendDTUpdateIndex; 0099 } 0100 0101 /// Returns true if there are PostDomTreeT updates queued. 0102 /// Returns false under Eager UpdateStrategy or PDT is nullptr. 0103 bool hasPendingPostDomTreeUpdates() const { 0104 if (!PDT) 0105 return false; 0106 return PendUpdates.size() != PendPDTUpdateIndex; 0107 } 0108 0109 ///@{ 0110 /// \name Mutation APIs 0111 /// 0112 /// These methods provide APIs for submitting updates to the DomTreeT and 0113 /// the PostDominatorTree. 0114 /// 0115 /// Note: There are two strategies to update the DomTreeT and the 0116 /// PostDominatorTree: 0117 /// 1. Eager UpdateStrategy: Updates are submitted and then flushed 0118 /// immediately. 0119 /// 2. Lazy UpdateStrategy: Updates are submitted but only flushed when you 0120 /// explicitly call Flush APIs. It is recommended to use this update strategy 0121 /// when you submit a bunch of updates multiple times which can then 0122 /// add up to a large number of updates between two queries on the 0123 /// DomTreeT. The incremental updater can reschedule the updates or 0124 /// decide to recalculate the dominator tree in order to speedup the updating 0125 /// process depending on the number of updates. 0126 /// 0127 /// Although GenericDomTree provides several update primitives, 0128 /// it is not encouraged to use these APIs directly. 0129 0130 /// Notify DTU that the entry block was replaced. 0131 /// Recalculate all available trees and flush all BasicBlocks 0132 /// awaiting deletion immediately. 0133 template <typename FuncT> void recalculate(FuncT &F); 0134 0135 /// Submit updates to all available trees. 0136 /// The Eager Strategy flushes updates immediately while the Lazy Strategy 0137 /// queues the updates. 0138 /// 0139 /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is 0140 /// in sync with + all updates before that single update. 0141 /// 0142 /// CAUTION! 0143 /// 1. It is required for the state of the LLVM IR to be updated 0144 /// *before* submitting the updates because the internal update routine will 0145 /// analyze the current state of the CFG to determine whether an update 0146 /// is valid. 0147 /// 2. It is illegal to submit any update that has already been submitted, 0148 /// i.e., you are supposed not to insert an existent edge or delete a 0149 /// nonexistent edge. 0150 void applyUpdates(ArrayRef<UpdateT> Updates); 0151 0152 /// Apply updates that the critical edge (FromBB, ToBB) has been 0153 /// split with NewBB. 0154 void splitCriticalEdge(BasicBlockT *FromBB, BasicBlockT *ToBB, 0155 BasicBlockT *NewBB); 0156 0157 /// Submit updates to all available trees. It will also 0158 /// 1. discard duplicated updates, 0159 /// 2. remove invalid updates. (Invalid updates means deletion of an edge that 0160 /// still exists or insertion of an edge that does not exist.) 0161 /// The Eager Strategy flushes updates immediately while the Lazy Strategy 0162 /// queues the updates. 0163 /// 0164 /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is 0165 /// in sync with + all updates before that single update. 0166 /// 0167 /// CAUTION! 0168 /// 1. It is required for the state of the LLVM IR to be updated 0169 /// *before* submitting the updates because the internal update routine will 0170 /// analyze the current state of the CFG to determine whether an update 0171 /// is valid. 0172 /// 2. It is illegal to submit any update that has already been submitted, 0173 /// i.e., you are supposed not to insert an existent edge or delete a 0174 /// nonexistent edge. 0175 /// 3. It is only legal to submit updates to an edge in the order CFG changes 0176 /// are made. The order you submit updates on different edges is not 0177 /// restricted. 0178 void applyUpdatesPermissive(ArrayRef<UpdateT> Updates); 0179 0180 ///@} 0181 0182 ///@{ 0183 /// \name Flush APIs 0184 /// 0185 /// CAUTION! By the moment these flush APIs are called, the current CFG needs 0186 /// to be the same as the CFG which DTU is in sync with + all updates 0187 /// submitted. 0188 0189 /// Flush DomTree updates and return DomTree. 0190 /// It flushes Deleted BBs if both trees are up-to-date. 0191 /// It must only be called when it has a DomTree. 0192 DomTreeT &getDomTree(); 0193 0194 /// Flush PostDomTree updates and return PostDomTree. 0195 /// It flushes Deleted BBs if both trees are up-to-date. 0196 /// It must only be called when it has a PostDomTree. 0197 PostDomTreeT &getPostDomTree(); 0198 0199 /// Apply all pending updates to available trees and flush all BasicBlocks 0200 /// awaiting deletion. 0201 0202 void flush() { 0203 applyDomTreeUpdates(); 0204 applyPostDomTreeUpdates(); 0205 dropOutOfDateUpdates(); 0206 } 0207 0208 ///@} 0209 0210 /// Debug method to help view the internal state of this class. 0211 LLVM_DUMP_METHOD void dump() const; 0212 0213 protected: 0214 /// Helper structure used to hold all the basic blocks 0215 /// involved in the split of a critical edge. 0216 struct CriticalEdge { 0217 BasicBlockT *FromBB; 0218 BasicBlockT *ToBB; 0219 BasicBlockT *NewBB; 0220 }; 0221 0222 struct DomTreeUpdate { 0223 bool IsCriticalEdgeSplit = false; 0224 union { 0225 UpdateT Update; 0226 CriticalEdge EdgeSplit; 0227 }; 0228 DomTreeUpdate(UpdateT Update) : Update(Update) {} 0229 DomTreeUpdate(CriticalEdge E) : IsCriticalEdgeSplit(true), EdgeSplit(E) {} 0230 }; 0231 0232 SmallVector<DomTreeUpdate, 16> PendUpdates; 0233 size_t PendDTUpdateIndex = 0; 0234 size_t PendPDTUpdateIndex = 0; 0235 DomTreeT *DT = nullptr; 0236 PostDomTreeT *PDT = nullptr; 0237 const UpdateStrategy Strategy; 0238 SmallPtrSet<BasicBlockT *, 8> DeletedBBs; 0239 bool IsRecalculatingDomTree = false; 0240 bool IsRecalculatingPostDomTree = false; 0241 0242 /// Returns true if the update is self dominance. 0243 bool isSelfDominance(UpdateT Update) const { 0244 // Won't affect DomTree and PostDomTree. 0245 return Update.getFrom() == Update.getTo(); 0246 } 0247 0248 /// Helper function to apply all pending DomTree updates. 0249 void applyDomTreeUpdates() { applyUpdatesImpl<true>(); } 0250 0251 /// Helper function to apply all pending PostDomTree updates. 0252 void applyPostDomTreeUpdates() { applyUpdatesImpl<false>(); } 0253 0254 /// Returns true if the update appears in the LLVM IR. 0255 /// It is used to check whether an update is valid in 0256 /// insertEdge/deleteEdge or is unnecessary in the batch update. 0257 bool isUpdateValid(UpdateT Update) const; 0258 0259 /// Erase Basic Block node before it is unlinked from Function 0260 /// in the DomTree and PostDomTree. 0261 void eraseDelBBNode(BasicBlockT *DelBB); 0262 0263 /// Helper function to flush deleted BasicBlocks if all available 0264 /// trees are up-to-date. 0265 void tryFlushDeletedBB(); 0266 0267 /// Drop all updates applied by all available trees and delete BasicBlocks if 0268 /// all available trees are up-to-date. 0269 void dropOutOfDateUpdates(); 0270 0271 private: 0272 void splitDTCriticalEdges(ArrayRef<CriticalEdge> Updates); 0273 void splitPDTCriticalEdges(ArrayRef<CriticalEdge> Updates); 0274 template <bool IsForward> void applyUpdatesImpl(); 0275 }; 0276 0277 } // namespace llvm 0278 0279 #endif // LLVM_ANALYSIS_GENERICDOMTREEUPDATER_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|