xref: /aosp_15_r20/external/clang/lib/Analysis/CFGReachabilityAnalysis.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines a flow-sensitive, (mostly) path-insensitive reachability
11*67e74705SXin Li // analysis based on Clang's CFGs.  Clients can query if a given basic block
12*67e74705SXin Li // is reachable within the CFG.
13*67e74705SXin Li //
14*67e74705SXin Li //===----------------------------------------------------------------------===//
15*67e74705SXin Li 
16*67e74705SXin Li #include "llvm/ADT/SmallVector.h"
17*67e74705SXin Li #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
18*67e74705SXin Li #include "clang/Analysis/CFG.h"
19*67e74705SXin Li 
20*67e74705SXin Li using namespace clang;
21*67e74705SXin Li 
CFGReverseBlockReachabilityAnalysis(const CFG & cfg)22*67e74705SXin Li CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg)
23*67e74705SXin Li   : analyzed(cfg.getNumBlockIDs(), false) {}
24*67e74705SXin Li 
isReachable(const CFGBlock * Src,const CFGBlock * Dst)25*67e74705SXin Li bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
26*67e74705SXin Li                                           const CFGBlock *Dst) {
27*67e74705SXin Li 
28*67e74705SXin Li   const unsigned DstBlockID = Dst->getBlockID();
29*67e74705SXin Li 
30*67e74705SXin Li   // If we haven't analyzed the destination node, run the analysis now
31*67e74705SXin Li   if (!analyzed[DstBlockID]) {
32*67e74705SXin Li     mapReachability(Dst);
33*67e74705SXin Li     analyzed[DstBlockID] = true;
34*67e74705SXin Li   }
35*67e74705SXin Li 
36*67e74705SXin Li   // Return the cached result
37*67e74705SXin Li   return reachable[DstBlockID][Src->getBlockID()];
38*67e74705SXin Li }
39*67e74705SXin Li 
40*67e74705SXin Li // Maps reachability to a common node by walking the predecessors of the
41*67e74705SXin Li // destination node.
mapReachability(const CFGBlock * Dst)42*67e74705SXin Li void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
43*67e74705SXin Li   SmallVector<const CFGBlock *, 11> worklist;
44*67e74705SXin Li   llvm::BitVector visited(analyzed.size());
45*67e74705SXin Li 
46*67e74705SXin Li   ReachableSet &DstReachability = reachable[Dst->getBlockID()];
47*67e74705SXin Li   DstReachability.resize(analyzed.size(), false);
48*67e74705SXin Li 
49*67e74705SXin Li   // Start searching from the destination node, since we commonly will perform
50*67e74705SXin Li   // multiple queries relating to a destination node.
51*67e74705SXin Li   worklist.push_back(Dst);
52*67e74705SXin Li   bool firstRun = true;
53*67e74705SXin Li 
54*67e74705SXin Li   while (!worklist.empty()) {
55*67e74705SXin Li     const CFGBlock *block = worklist.pop_back_val();
56*67e74705SXin Li 
57*67e74705SXin Li     if (visited[block->getBlockID()])
58*67e74705SXin Li       continue;
59*67e74705SXin Li     visited[block->getBlockID()] = true;
60*67e74705SXin Li 
61*67e74705SXin Li     // Update reachability information for this node -> Dst
62*67e74705SXin Li     if (!firstRun) {
63*67e74705SXin Li       // Don't insert Dst -> Dst unless it was a predecessor of itself
64*67e74705SXin Li       DstReachability[block->getBlockID()] = true;
65*67e74705SXin Li     }
66*67e74705SXin Li     else
67*67e74705SXin Li       firstRun = false;
68*67e74705SXin Li 
69*67e74705SXin Li     // Add the predecessors to the worklist.
70*67e74705SXin Li     for (CFGBlock::const_pred_iterator i = block->pred_begin(),
71*67e74705SXin Li          e = block->pred_end(); i != e; ++i) {
72*67e74705SXin Li       if (*i)
73*67e74705SXin Li         worklist.push_back(*i);
74*67e74705SXin Li     }
75*67e74705SXin Li   }
76*67e74705SXin Li }
77