Back to home page

EIC code displayed by LXR

 
 

    


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