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