clang 22.0.0git
LoanPropagation.cpp
Go to the documentation of this file.
1//===- LoanPropagation.cpp - Loan Propagation Analysis ---------*- 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//===----------------------------------------------------------------------===//
9#include "Dataflow.h"
10#include <memory>
11
13namespace {
14/// Represents the dataflow lattice for loan propagation.
15///
16/// This lattice tracks which loans each origin may hold at a given program
17/// point.The lattice has a finite height: An origin's loan set is bounded by
18/// the total number of loans in the function.
19/// TODO(opt): To reduce the lattice size, propagate origins of declarations,
20/// not expressions, because expressions are not visible across blocks.
21struct Lattice {
22 /// The map from an origin to the set of loans it contains.
23 OriginLoanMap Origins = OriginLoanMap(nullptr);
24
25 explicit Lattice(const OriginLoanMap &S) : Origins(S) {}
26 Lattice() = default;
27
28 bool operator==(const Lattice &Other) const {
29 return Origins == Other.Origins;
30 }
31 bool operator!=(const Lattice &Other) const { return !(*this == Other); }
32
33 void dump(llvm::raw_ostream &OS) const {
34 OS << "LoanPropagationLattice State:\n";
35 if (Origins.isEmpty())
36 OS << " <empty>\n";
37 for (const auto &Entry : Origins) {
38 if (Entry.second.isEmpty())
39 OS << " Origin " << Entry.first << " contains no loans\n";
40 for (const LoanID &LID : Entry.second)
41 OS << " Origin " << Entry.first << " contains Loan " << LID << "\n";
42 }
43 }
44};
45
46class AnalysisImpl
47 : public DataflowAnalysis<AnalysisImpl, Lattice, Direction::Forward> {
48public:
49 AnalysisImpl(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
50 OriginLoanMap::Factory &OriginLoanMapFactory,
51 LoanSet::Factory &LoanSetFactory)
52 : DataflowAnalysis(C, AC, F), OriginLoanMapFactory(OriginLoanMapFactory),
53 LoanSetFactory(LoanSetFactory) {}
54
55 using Base::transfer;
56
57 StringRef getAnalysisName() const { return "LoanPropagation"; }
58
59 Lattice getInitialState() { return Lattice{}; }
60
61 /// Merges two lattices by taking the union of loans for each origin.
62 // TODO(opt): Keep the state small by removing origins which become dead.
63 Lattice join(Lattice A, Lattice B) {
64 OriginLoanMap JoinedOrigins = utils::join(
65 A.Origins, B.Origins, OriginLoanMapFactory,
66 [&](const LoanSet *S1, const LoanSet *S2) {
67 assert((S1 || S2) && "unexpectedly merging 2 empty sets");
68 if (!S1)
69 return *S2;
70 if (!S2)
71 return *S1;
72 return utils::join(*S1, *S2, LoanSetFactory);
73 },
74 // Asymmetric join is a performance win. For origins present only on one
75 // branch, the loan set can be carried over as-is.
77 return Lattice(JoinedOrigins);
78 }
79
80 /// A new loan is issued to the origin. Old loans are erased.
81 Lattice transfer(Lattice In, const IssueFact &F) {
82 OriginID OID = F.getOriginID();
83 LoanID LID = F.getLoanID();
84 return Lattice(OriginLoanMapFactory.add(
85 In.Origins, OID,
86 LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID)));
87 }
88
89 /// A flow from source to destination. If `KillDest` is true, this replaces
90 /// the destination's loans with the source's. Otherwise, the source's loans
91 /// are merged into the destination's.
92 Lattice transfer(Lattice In, const OriginFlowFact &F) {
93 OriginID DestOID = F.getDestOriginID();
94 OriginID SrcOID = F.getSrcOriginID();
95
96 LoanSet DestLoans =
97 F.getKillDest() ? LoanSetFactory.getEmptySet() : getLoans(In, DestOID);
98 LoanSet SrcLoans = getLoans(In, SrcOID);
99 LoanSet MergedLoans = utils::join(DestLoans, SrcLoans, LoanSetFactory);
100
101 return Lattice(OriginLoanMapFactory.add(In.Origins, DestOID, MergedLoans));
102 }
103
104 LoanSet getLoans(OriginID OID, ProgramPoint P) const {
105 return getLoans(getState(P), OID);
106 }
107
108private:
109 LoanSet getLoans(Lattice L, OriginID OID) const {
110 if (auto *Loans = L.Origins.lookup(OID))
111 return *Loans;
112 return LoanSetFactory.getEmptySet();
113 }
114
115 OriginLoanMap::Factory &OriginLoanMapFactory;
116 LoanSet::Factory &LoanSetFactory;
117};
118} // namespace
119
120class LoanPropagationAnalysis::Impl final : public AnalysisImpl {
121 using AnalysisImpl::AnalysisImpl;
122};
123
125 const CFG &C, AnalysisDeclContext &AC, FactManager &F,
126 OriginLoanMap::Factory &OriginLoanMapFactory,
127 LoanSet::Factory &LoanSetFactory)
128 : PImpl(std::make_unique<Impl>(C, AC, F, OriginLoanMapFactory,
129 LoanSetFactory)) {
130 PImpl->run();
131}
132
134
136 return PImpl->getLoans(OID, P);
137}
138} // namespace clang::lifetimes::internal
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1222
A generic, policy-based driver for dataflow analyses.
Definition Dataflow.h:57
LoanSet getLoans(OriginID OID, ProgramPoint P) const
LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, LoanSet::Factory &LoanSetFactory)
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)
Evaluates S and updates Env accordingly.
Definition Transfer.cpp:956
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ Asymmetric
An asymmetric join preserves keys unique to the first map as-is, while applying the JoinValues operat...
Definition Utils.h:62
static llvm::ImmutableSet< T > join(llvm::ImmutableSet< T > A, llvm::ImmutableSet< T > B, typename llvm::ImmutableSet< T >::Factory &F)
Computes the union of two ImmutableSets.
Definition Utils.h:39
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
Definition Facts.h:74
llvm::ImmutableSet< LoanID > LoanSet
utils::ID< struct LoanTag > LoanID
Definition Loans.h:23
utils::ID< struct OriginTag > OriginID
Definition Origins.h:23
llvm::ImmutableMap< OriginID, LoanSet > OriginLoanMap
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition CallGraph.h:204
bool operator!=(CanQual< T > x, CanQual< U > y)
@ Other
Other implicit parameter.
Definition Decl.h:1746