|
|
|||
File indexing completed on 2026-05-10 08:36:23
0001 //===- IntervalPartition.h - CFG Partitioning into Intervals -----*- 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 functionality for partitioning a CFG into intervals and 0010 // building a weak topological order (WTO) of the nodes, based on the 0011 // partitioning. The concepts and implementations for the graph partitioning 0012 // are based on the presentation in "Compilers" by Aho, Sethi and Ullman (the 0013 // "dragon book"), pages 664-666. The concepts around WTOs is taken from the 0014 // paper "Efficient chaotic iteration strategies with widenings," by 0015 // F. Bourdoncle ([Bourdoncle1993]). 0016 // 0017 //===----------------------------------------------------------------------===// 0018 0019 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H 0020 #define LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H 0021 0022 #include "clang/Analysis/CFG.h" 0023 #include "llvm/ADT/DenseSet.h" 0024 #include <deque> 0025 #include <memory> 0026 #include <vector> 0027 0028 namespace clang { 0029 /// A _weak topological ordering_ (WTO) of CFG nodes provides a total order over 0030 /// the CFG (defined in `WTOCompare`, below), which can guide the order in which 0031 /// to visit nodes in fixpoint computations over the CFG. 0032 /// 0033 /// Roughly, a WTO a) groups the blocks so that loop heads are grouped with 0034 /// their bodies and any nodes they dominate after the loop and b) orders the 0035 /// groups topologically. As a result, the blocks in a series of loops are 0036 /// ordered such that all nodes in loop `i` are earlier in the order than nodes 0037 /// in loop `j`. This ordering, when combined with widening, bounds the number 0038 /// of times a node must be visited for a dataflow algorithm to reach a 0039 /// fixpoint. For the precise definition of a WTO and its properties, see 0040 /// [Bourdoncle1993]. 0041 /// 0042 /// Here, we provide a simplified WTO which drops its nesting structure, 0043 /// maintaining only the ordering itself. The ordering is built from the limit 0044 /// flow graph of `Cfg` (derived from iteratively partitioning it into 0045 /// intervals) if and only if it is reducible (its limit flow graph has one 0046 /// node). Returns `nullopt` when `Cfg` is not reducible. 0047 /// 0048 /// This WTO construction is described in Section 4.2 of [Bourdoncle1993]. 0049 using WeakTopologicalOrdering = std::vector<const CFGBlock *>; 0050 std::optional<WeakTopologicalOrdering> getIntervalWTO(const CFG &Cfg); 0051 0052 struct WTOCompare { 0053 WTOCompare(const WeakTopologicalOrdering &WTO); 0054 0055 bool operator()(const CFGBlock *B1, const CFGBlock *B2) const { 0056 auto ID1 = B1->getBlockID(); 0057 auto ID2 = B2->getBlockID(); 0058 0059 unsigned V1 = ID1 >= BlockOrder.size() ? 0 : BlockOrder[ID1]; 0060 unsigned V2 = ID2 >= BlockOrder.size() ? 0 : BlockOrder[ID2]; 0061 return V1 > V2; 0062 } 0063 0064 std::vector<unsigned> BlockOrder; 0065 }; 0066 0067 namespace internal { 0068 // An interval is a strongly-connected component of the CFG along with a 0069 // trailing acyclic structure. An interval can be constructed directly from CFG 0070 // blocks or from a graph of other intervals. Each interval has one _header_ 0071 // block, from which the interval is built. The _header_ of the interval is 0072 // either the graph's entry block or has at least one predecessor outside of the 0073 // interval. All other blocks in the interval have only predecessors also in the 0074 // interval. 0075 struct CFGIntervalNode { 0076 CFGIntervalNode() = default; 0077 CFGIntervalNode(unsigned ID) : ID(ID) {} 0078 0079 CFGIntervalNode(unsigned ID, std::vector<const CFGBlock *> Nodes) 0080 : ID(ID), Nodes(std::move(Nodes)) {} 0081 0082 const llvm::SmallDenseSet<const CFGIntervalNode *> &preds() const { 0083 return Predecessors; 0084 } 0085 const llvm::SmallDenseSet<const CFGIntervalNode *> &succs() const { 0086 return Successors; 0087 } 0088 0089 // Unique identifier of this interval relative to other intervals in the same 0090 // graph. 0091 unsigned ID; 0092 0093 std::vector<const CFGBlock *> Nodes; 0094 0095 // Predessor intervals of this interval: those intervals for which there 0096 // exists an edge from a node in that other interval to the head of this 0097 // interval. 0098 llvm::SmallDenseSet<const CFGIntervalNode *> Predecessors; 0099 0100 // Successor intervals of this interval: those intervals for which there 0101 // exists an edge from a node in this interval to the head of that other 0102 // interval. 0103 llvm::SmallDenseSet<const CFGIntervalNode *> Successors; 0104 }; 0105 0106 // Since graphs are built from pointers to nodes, we use a deque to ensure 0107 // pointer stability. 0108 using CFGIntervalGraph = std::deque<CFGIntervalNode>; 0109 0110 std::vector<const CFGBlock *> buildInterval(const CFGBlock *Header); 0111 0112 // Partitions `Cfg` into intervals and constructs the graph of the intervals 0113 // based on the edges between nodes in these intervals. 0114 CFGIntervalGraph partitionIntoIntervals(const CFG &Cfg); 0115 0116 // (Further) partitions `Graph` into intervals and constructs the graph of the 0117 // intervals based on the edges between nodes (themselves intervals) in these 0118 // intervals. 0119 CFGIntervalGraph partitionIntoIntervals(const CFGIntervalGraph &Graph); 0120 } // namespace internal 0121 } // namespace clang 0122 0123 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_INTERVALPARTITION_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|