14#include "llvm/ADT/PriorityQueue.h"
15#include "llvm/ADT/DenseSet.h"
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/Statistic.h"
25#define DEBUG_TYPE "WorkList"
27STATISTIC(MaxQueueSize,
"Maximum size of the worklist");
28STATISTIC(MaxReachableSize,
"Maximum size of auxiliary worklist set");
41 return !Stack.empty();
49 assert(!Stack.empty());
57 std::deque<WorkListUnit> Queue;
61 return !Queue.empty();
82 return std::make_unique<DFS>();
86 return std::make_unique<BFS>();
92 std::deque<WorkListUnit> Queue;
96 bool hasWork()
const override {
97 return !Queue.empty() || !Stack.empty();
109 if (!Stack.empty()) {
115 assert(!Queue.empty());
127 return std::make_unique<BFSBlockDFSContents>();
132class UnexploredFirstStack :
public WorkList {
140 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
142 llvm::DenseSet<LocIdentifier> Reachable;
145 bool hasWork()
const override {
146 return !(StackUnexplored.empty() && StackOthers.empty());
156 StackUnexplored.push_back(
U);
158 LocIdentifier LocId = std::make_pair(
159 BE->getBlock()->getBlockID(),
161 auto InsertInfo = Reachable.insert(LocId);
163 if (InsertInfo.second) {
164 StackUnexplored.push_back(
U);
166 StackOthers.push_back(
U);
169 MaxReachableSize.updateMax(Reachable.size());
170 MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
174 if (!StackUnexplored.empty()) {
176 StackUnexplored.pop_back();
180 StackOthers.pop_back();
189 return std::make_unique<UnexploredFirstStack>();
193class UnexploredFirstPriorityQueue :
public WorkList {
195 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
200 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
205 using QueuePriority = std::pair<int, unsigned long>;
206 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
210 unsigned long Counter = 0;
213 VisitedTimesMap NumReached;
216 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, llvm::less_second>
220 bool hasWork()
const override {
221 return !queue.empty();
226 unsigned NumVisited = 0;
228 LocIdentifier LocId = std::make_pair(
229 BE->getBlock()->getBlockID(),
231 NumVisited = NumReached[LocId]++;
234 queue.push(std::make_pair(
U, std::make_pair(-NumVisited, ++Counter)));
238 QueueItem
U = queue.top();
246 return std::make_unique<UnexploredFirstPriorityQueue>();
250class UnexploredFirstPriorityLocationQueue :
public WorkList {
251 using LocIdentifier =
const CFGBlock *;
256 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
261 using QueuePriority = std::pair<int, unsigned long>;
262 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
266 unsigned long Counter = 0;
269 VisitedTimesMap NumReached;
272 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, llvm::less_second>
276 bool hasWork()
const override {
277 return !queue.
empty();
282 unsigned NumVisited = 0;
284 NumVisited = NumReached[BE->getBlock()]++;
286 queue.push(std::make_pair(
U, std::make_pair(-NumVisited, ++Counter)));
290 QueueItem
U = queue.top();
300 return std::make_unique<UnexploredFirstPriorityLocationQueue>();
STATISTIC(MaxQueueSize, "Maximum size of the worklist")
Represents a single basic block in a source-level CFG.
const StackFrameContext * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const LocationContext * getLocationContext() const
virtual bool hasWork() const =0
static std::unique_ptr< WorkList > makeUnexploredFirstPriorityLocationQueue()
static std::unique_ptr< WorkList > makeUnexploredFirstPriorityQueue()
static std::unique_ptr< WorkList > makeBFSBlockDFSContents()
virtual WorkListUnit dequeue()=0
static std::unique_ptr< WorkList > makeBFS()
static std::unique_ptr< WorkList > makeDFS()
static std::unique_ptr< WorkList > makeUnexploredFirst()
virtual void enqueue(const WorkListUnit &U)=0
The JSON file list parser is used to communicate input to InstallAPI.