xref: /llvm-project/llvm/include/llvm/Analysis/EHUtils.h (revision f8bd98b3f1e6e71f489f592effb1c96b863ac08c)
1 //===-- Analysis/EHUtils.h - Exception handling related utils --*-//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 #ifndef LLVM_ANALYSIS_EHUTILS_H
9 #define LLVM_ANALYSIS_EHUTILS_H
10 
11 #include "llvm/ADT/DenseMap.h"
12 #include "llvm/ADT/DenseSet.h"
13 
14 namespace llvm {
15 
16 /// Compute a list of blocks that are only reachable via EH paths.
17 template <typename FunctionT, typename BlockT>
18 static void computeEHOnlyBlocks(FunctionT &F, DenseSet<BlockT *> &EHBlocks) {
19   // A block can be unknown if its not reachable from anywhere
20   // EH if its only reachable from start blocks via some path through EH pads
21   // NonEH if it's reachable from Non EH blocks as well.
22   enum Status { Unknown = 0, EH = 1, NonEH = 2 };
23   DenseSet<BlockT *> WorkList;
24   DenseMap<BlockT *, Status> Statuses;
25 
26   auto GetStatus = [&](BlockT *BB) {
27     auto It = Statuses.find(BB);
28     return It != Statuses.end() ? It->second : Unknown;
29   };
30 
31   auto CheckPredecessors = [&](BlockT *BB, Status Stat) {
32     for (auto *PredBB : predecessors(BB)) {
33       Status PredStatus = GetStatus(PredBB);
34       // If status of predecessor block has gone above current block
35       // we update current blocks status.
36       if (PredStatus > Stat)
37         Stat = PredStatus;
38     }
39     return Stat;
40   };
41 
42   auto AddSuccesors = [&](BlockT *BB) {
43     for (auto *SuccBB : successors(BB)) {
44       if (!SuccBB->isEHPad())
45         WorkList.insert(SuccBB);
46     }
47   };
48 
49   // Insert the successors of start block and landing pads successor.
50   BlockT *StartBlock = &F.front();
51   Statuses[StartBlock] = NonEH;
52   AddSuccesors(StartBlock);
53 
54   for (auto &BB : F) {
55     if (BB.isEHPad()) {
56       AddSuccesors(&BB);
57       Statuses[&BB] = EH;
58     }
59   }
60 
61   // Worklist iterative algorithm.
62   while (!WorkList.empty()) {
63     auto *BB = *WorkList.begin();
64     WorkList.erase(BB);
65 
66     Status OldStatus = GetStatus(BB);
67 
68     // Check on predecessors and check for
69     // Status update.
70     Status NewStatus = CheckPredecessors(BB, OldStatus);
71 
72     // Did the block status change?
73     bool Changed = OldStatus != NewStatus;
74     if (Changed) {
75       AddSuccesors(BB);
76       Statuses[BB] = NewStatus;
77     }
78   }
79 
80   for (auto Entry : Statuses) {
81     if (Entry.second == EH)
82       EHBlocks.insert(Entry.first);
83   }
84 }
85 } // namespace llvm
86 
87 #endif
88