12#include "llvm/Support/ErrorHandling.h"
29 : Persistent(Persistent), BlockLocal(BlockLocal) {}
32 return Persistent ==
Other.Persistent && BlockLocal ==
Other.BlockLocal;
37 void dump(llvm::raw_ostream &OS,
const OriginManager &OM)
const {
38 if (Persistent.isEmpty() && BlockLocal.isEmpty())
40 for (
const LivenessMap &Live : {Persistent, BlockLocal})
41 for (
const auto &Entry : Live) {
43 const LivenessInfo &Info = Entry.second;
55 llvm_unreachable(
"liveness kind of live origins should not be dead.");
57 OS <<
" live at this point\n";
63 if (
const auto *UF = dyn_cast<const UseFact *>(F))
64 return UF->getUseSite().getLoc();
65 if (
const auto *OEF = dyn_cast<const OriginEscapesFact *>(F)) {
66 if (
auto *ReturnEsc = dyn_cast<ReturnEscapeFact>(OEF))
67 return ReturnEsc->getReturnExpr()->getExprLoc();
68 if (
auto *FieldEsc = dyn_cast<FieldEscapeFact>(OEF))
69 return FieldEsc->getFieldDecl()->getLocation();
70 if (
auto *GlobalEsc = dyn_cast<GlobalEscapeFact>(OEF))
71 return GlobalEsc->getGlobal()->getLocation();
72 if (
auto *ThisEsc = dyn_cast<ThisEscapeFact>(OEF))
73 return ThisEsc->getLoc();
75 llvm_unreachable(
"unhandled causing fact in PointerUnion");
85 AnalysisImpl(
const CFG &
C, AnalysisDeclContext &AC, FactManager &F,
86 LivenessMap::Factory &SF)
87 : DataflowAnalysis(
C, AC, F), FactMgr(F), Factory(SF),
88 PersistentOrigins(F.getPersistentOrigins()) {}
91 StringRef getAnalysisName()
const {
return "LiveOrigins"; }
93 Lattice getInitialState() {
94 return Lattice(Factory.getEmptyMap(), Factory.getEmptyMap());
105 Lattice transferAtBlockExit(Lattice L) {
106 return Lattice(L.Persistent, Factory.getEmptyMap());
112 Lattice
join(Lattice L1, Lattice L2)
const {
113 assert(L1.BlockLocal.isEmpty() && L2.BlockLocal.isEmpty() &&
114 "block-local origins must not reach a block boundary");
122 return GetFactLoc(A) < GetFactLoc(B) ? A : B;
133 auto CombineLivenessInfo = [&](
const LivenessInfo *L1,
134 const LivenessInfo *L2) -> LivenessInfo {
135 assert((L1 || L2) &&
"unexpectedly merging 2 empty sets");
140 return LivenessInfo(CombineCausingFact(L1->CausingFact, L2->CausingFact),
141 CombineLivenessKind(L1->Kind, L2->Kind));
146 utils::join(L1.Persistent, L2.Persistent, Factory, CombineLivenessInfo,
148 return Lattice(Joined, Factory.getEmptyMap());
153 Lattice
transfer(Lattice In,
const UseFact &UF) {
155 for (
const OriginList *Cur = UF.getUsedOrigins(); Cur;
156 Cur = Cur->peelOuterOrigin())
157 Out = addLive(Out, Cur->getOuterOriginID(),
164 Lattice
transfer(Lattice In,
const OriginEscapesFact &OEF) {
165 return addLive(In, OEF.getEscapedOriginID(),
170 Lattice
transfer(Lattice In,
const IssueFact &IF) {
171 return removeLive(In, IF.getOriginID());
176 Lattice
transfer(Lattice In,
const OriginFlowFact &OF) {
178 OriginID Dest = OF.getDestOriginID();
182 if (
const LivenessInfo *DestInfo = lookupLive(In, Dest))
183 Out = addLive(Out, OF.getSrcOriginID(), *DestInfo);
184 if (OF.getKillDest())
185 Out = removeLive(Out, Dest);
189 Lattice
transfer(Lattice In,
const KillOriginFact &F) {
190 return removeLive(In, F.getKilledOrigin());
193 Lattice
transfer(Lattice In,
const ExpireFact &F) {
194 if (
auto OID = F.getOriginID())
195 return removeLive(In, *OID);
200 Lattice L = getState(P);
201 return LiveOriginSet{L.Persistent, L.BlockLocal};
205 void dump(llvm::raw_ostream &OS,
206 const llvm::StringMap<ProgramPoint> &TestPoints)
const {
207 llvm::dbgs() <<
"==========================================\n";
208 llvm::dbgs() << getAnalysisName() <<
" results:\n";
209 llvm::dbgs() <<
"==========================================\n";
210 for (
const auto &Entry : TestPoints) {
211 OS <<
"TestPoint: " << Entry.getKey() <<
"\n";
212 getState(Entry.getValue()).dump(OS, FactMgr.getOriginMgr());
218 bool isPersistent(
OriginID OID)
const {
219 return PersistentOrigins.test(OID.Value);
222 Lattice addLive(Lattice L,
OriginID OID, LivenessInfo Info) {
223 if (isPersistent(OID))
224 return Lattice(Factory.add(L.Persistent, OID, Info), L.BlockLocal);
225 return Lattice(L.Persistent, Factory.add(L.BlockLocal, OID, Info));
228 Lattice removeLive(Lattice L,
OriginID OID) {
229 if (isPersistent(OID))
230 return Lattice(Factory.remove(L.Persistent, OID), L.BlockLocal);
231 return Lattice(L.Persistent, Factory.remove(L.BlockLocal, OID));
234 const LivenessInfo *lookupLive(
const Lattice &L,
OriginID OID)
const {
235 return isPersistent(OID) ? L.Persistent.lookup(OID)
236 : L.BlockLocal.lookup(OID);
239 FactManager &FactMgr;
240 LivenessMap::Factory &Factory;
243 const llvm::BitVector &PersistentOrigins;
249 using AnalysisImpl::AnalysisImpl;
254 LivenessMap::Factory &SF)
255 : PImpl(
std::make_unique<
Impl>(
C, AC, F, SF)) {
262 return PImpl->getLiveOriginsAt(P);
266 llvm::raw_ostream &OS,
267 const llvm::StringMap<ProgramPoint> &TestPoints)
const {
268 PImpl->dump(OS, TestPoints);
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.
A generic, policy-based driver for dataflow analyses.
LiveOriginSet getLiveOriginsAt(ProgramPoint P) const
Returns the set of origins that are live at a specific program point, along with the the details of t...
LiveOriginsAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, LivenessMap::Factory &SF)
void dump(llvm::raw_ostream &OS, const llvm::StringMap< ProgramPoint > &TestPoints) const
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)
Evaluates S and updates Env accordingly.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ Symmetric
A symmetric join applies the JoinValues operation to keys unique to either map, ensuring that values ...
SetTy< T > join(SetTy< T > A, SetTy< T > B, typename SetTy< T >::Factory &F)
Computes the union of two ImmutableSets.
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
utils::ID< struct OriginTag > OriginID
::llvm::PointerUnion< const UseFact *, const OriginEscapesFact * > CausingFactType
utils::MapTy< OriginID, LivenessInfo > LivenessMap
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator!=(CanQual< T > x, CanQual< U > y)
@ Other
Other implicit parameter.
The origins that are live at a program point.