xref: /freebsd-src/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements Live Variables analysis for source-level CFGs.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Analysis/Analyses/LiveVariables.h"
140b57cec5SDimitry Andric #include "clang/AST/Stmt.h"
150b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h"
160b57cec5SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h"
170b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
185ffd83dbSDimitry Andric #include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
190b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <algorithm>
22*bdd1243dSDimitry Andric #include <optional>
230b57cec5SDimitry Andric #include <vector>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace clang;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace {
280b57cec5SDimitry Andric class LiveVariablesImpl {
290b57cec5SDimitry Andric public:
300b57cec5SDimitry Andric   AnalysisDeclContext &analysisContext;
31e8d8bef9SDimitry Andric   llvm::ImmutableSet<const Expr *>::Factory ESetFact;
320b57cec5SDimitry Andric   llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
330b57cec5SDimitry Andric   llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;
340b57cec5SDimitry Andric   llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
350b57cec5SDimitry Andric   llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
360b57cec5SDimitry Andric   llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
370b57cec5SDimitry Andric   llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
380b57cec5SDimitry Andric   const bool killAtAssign;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   LiveVariables::LivenessValues
410b57cec5SDimitry Andric   merge(LiveVariables::LivenessValues valsA,
420b57cec5SDimitry Andric         LiveVariables::LivenessValues valsB);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   LiveVariables::LivenessValues
450b57cec5SDimitry Andric   runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,
460b57cec5SDimitry Andric              LiveVariables::Observer *obs = nullptr);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   void dumpBlockLiveness(const SourceManager& M);
49e8d8bef9SDimitry Andric   void dumpExprLiveness(const SourceManager& M);
500b57cec5SDimitry Andric 
LiveVariablesImpl(AnalysisDeclContext & ac,bool KillAtAssign)510b57cec5SDimitry Andric   LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
520b57cec5SDimitry Andric       : analysisContext(ac),
53e8d8bef9SDimitry Andric         ESetFact(false), // Do not canonicalize ImmutableSets by default.
540b57cec5SDimitry Andric         DSetFact(false), // This is a *major* performance win.
55e8d8bef9SDimitry Andric         BSetFact(false), killAtAssign(KillAtAssign) {}
560b57cec5SDimitry Andric };
57e8d8bef9SDimitry Andric } // namespace
580b57cec5SDimitry Andric 
getImpl(void * x)590b57cec5SDimitry Andric static LiveVariablesImpl &getImpl(void *x) {
600b57cec5SDimitry Andric   return *((LiveVariablesImpl *) x);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
640b57cec5SDimitry Andric // Operations and queries on LivenessValues.
650b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
660b57cec5SDimitry Andric 
isLive(const Expr * E) const67e8d8bef9SDimitry Andric bool LiveVariables::LivenessValues::isLive(const Expr *E) const {
68e8d8bef9SDimitry Andric   return liveExprs.contains(E);
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
isLive(const VarDecl * D) const710b57cec5SDimitry Andric bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
720b57cec5SDimitry Andric   if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {
730b57cec5SDimitry Andric     bool alive = false;
740b57cec5SDimitry Andric     for (const BindingDecl *BD : DD->bindings())
750b57cec5SDimitry Andric       alive |= liveBindings.contains(BD);
76972a253aSDimitry Andric 
77972a253aSDimitry Andric     // Note: the only known case this condition is necessary, is when a bindig
78972a253aSDimitry Andric     // to a tuple-like structure is created. The HoldingVar initializers have a
79972a253aSDimitry Andric     // DeclRefExpr to the DecompositionDecl.
80972a253aSDimitry Andric     alive |= liveDecls.contains(DD);
810b57cec5SDimitry Andric     return alive;
820b57cec5SDimitry Andric   }
830b57cec5SDimitry Andric   return liveDecls.contains(D);
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric namespace {
870b57cec5SDimitry Andric   template <typename SET>
mergeSets(SET A,SET B)880b57cec5SDimitry Andric   SET mergeSets(SET A, SET B) {
890b57cec5SDimitry Andric     if (A.isEmpty())
900b57cec5SDimitry Andric       return B;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
930b57cec5SDimitry Andric       A = A.add(*it);
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric     return A;
960b57cec5SDimitry Andric   }
975ffd83dbSDimitry Andric } // namespace
980b57cec5SDimitry Andric 
anchor()990b57cec5SDimitry Andric void LiveVariables::Observer::anchor() { }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric LiveVariables::LivenessValues
merge(LiveVariables::LivenessValues valsA,LiveVariables::LivenessValues valsB)1020b57cec5SDimitry Andric LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
1030b57cec5SDimitry Andric                          LiveVariables::LivenessValues valsB) {
1040b57cec5SDimitry Andric 
105e8d8bef9SDimitry Andric   llvm::ImmutableSetRef<const Expr *> SSetRefA(
106e8d8bef9SDimitry Andric       valsA.liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),
107e8d8bef9SDimitry Andric       SSetRefB(valsB.liveExprs.getRootWithoutRetain(),
108e8d8bef9SDimitry Andric                ESetFact.getTreeFactory());
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   llvm::ImmutableSetRef<const VarDecl *>
1110b57cec5SDimitry Andric     DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
1120b57cec5SDimitry Andric     DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   llvm::ImmutableSetRef<const BindingDecl *>
1150b57cec5SDimitry Andric     BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
1160b57cec5SDimitry Andric     BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   SSetRefA = mergeSets(SSetRefA, SSetRefB);
1190b57cec5SDimitry Andric   DSetRefA = mergeSets(DSetRefA, DSetRefB);
1200b57cec5SDimitry Andric   BSetRefA = mergeSets(BSetRefA, BSetRefB);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // asImmutableSet() canonicalizes the tree, allowing us to do an easy
1230b57cec5SDimitry Andric   // comparison afterwards.
1240b57cec5SDimitry Andric   return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
1250b57cec5SDimitry Andric                                        DSetRefA.asImmutableSet(),
1260b57cec5SDimitry Andric                                        BSetRefA.asImmutableSet());
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
equals(const LivenessValues & V) const1290b57cec5SDimitry Andric bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
130e8d8bef9SDimitry Andric   return liveExprs == V.liveExprs && liveDecls == V.liveDecls;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1340b57cec5SDimitry Andric // Query methods.
1350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1360b57cec5SDimitry Andric 
isAlwaysAlive(const VarDecl * D)1370b57cec5SDimitry Andric static bool isAlwaysAlive(const VarDecl *D) {
1380b57cec5SDimitry Andric   return D->hasGlobalStorage();
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
isLive(const CFGBlock * B,const VarDecl * D)1410b57cec5SDimitry Andric bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
1420b57cec5SDimitry Andric   return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
isLive(const Stmt * S,const VarDecl * D)1450b57cec5SDimitry Andric bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
1460b57cec5SDimitry Andric   return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
isLive(const Stmt * Loc,const Expr * Val)149e8d8bef9SDimitry Andric bool LiveVariables::isLive(const Stmt *Loc, const Expr *Val) {
150e8d8bef9SDimitry Andric   return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1540b57cec5SDimitry Andric // Dataflow computation.
1550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric namespace {
1580b57cec5SDimitry Andric class TransferFunctions : public StmtVisitor<TransferFunctions> {
1590b57cec5SDimitry Andric   LiveVariablesImpl &LV;
1600b57cec5SDimitry Andric   LiveVariables::LivenessValues &val;
1610b57cec5SDimitry Andric   LiveVariables::Observer *observer;
1620b57cec5SDimitry Andric   const CFGBlock *currentBlock;
1630b57cec5SDimitry Andric public:
TransferFunctions(LiveVariablesImpl & im,LiveVariables::LivenessValues & Val,LiveVariables::Observer * Observer,const CFGBlock * CurrentBlock)1640b57cec5SDimitry Andric   TransferFunctions(LiveVariablesImpl &im,
1650b57cec5SDimitry Andric                     LiveVariables::LivenessValues &Val,
1660b57cec5SDimitry Andric                     LiveVariables::Observer *Observer,
1670b57cec5SDimitry Andric                     const CFGBlock *CurrentBlock)
1680b57cec5SDimitry Andric   : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   void VisitBinaryOperator(BinaryOperator *BO);
1710b57cec5SDimitry Andric   void VisitBlockExpr(BlockExpr *BE);
1720b57cec5SDimitry Andric   void VisitDeclRefExpr(DeclRefExpr *DR);
1730b57cec5SDimitry Andric   void VisitDeclStmt(DeclStmt *DS);
1740b57cec5SDimitry Andric   void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
1750b57cec5SDimitry Andric   void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
1760b57cec5SDimitry Andric   void VisitUnaryOperator(UnaryOperator *UO);
1770b57cec5SDimitry Andric   void Visit(Stmt *S);
1780b57cec5SDimitry Andric };
1795ffd83dbSDimitry Andric } // namespace
1800b57cec5SDimitry Andric 
FindVA(QualType Ty)1810b57cec5SDimitry Andric static const VariableArrayType *FindVA(QualType Ty) {
1820b57cec5SDimitry Andric   const Type *ty = Ty.getTypePtr();
1830b57cec5SDimitry Andric   while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
1840b57cec5SDimitry Andric     if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
1850b57cec5SDimitry Andric       if (VAT->getSizeExpr())
1860b57cec5SDimitry Andric         return VAT;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric     ty = VT->getElementType().getTypePtr();
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   return nullptr;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric 
LookThroughExpr(const Expr * E)194e8d8bef9SDimitry Andric static const Expr *LookThroughExpr(const Expr *E) {
195e8d8bef9SDimitry Andric   while (E) {
196e8d8bef9SDimitry Andric     if (const Expr *Ex = dyn_cast<Expr>(E))
197e8d8bef9SDimitry Andric       E = Ex->IgnoreParens();
198e8d8bef9SDimitry Andric     if (const FullExpr *FE = dyn_cast<FullExpr>(E)) {
199e8d8bef9SDimitry Andric       E = FE->getSubExpr();
2000b57cec5SDimitry Andric       continue;
2010b57cec5SDimitry Andric     }
202e8d8bef9SDimitry Andric     if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
203e8d8bef9SDimitry Andric       E = OVE->getSourceExpr();
2040b57cec5SDimitry Andric       continue;
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric     break;
2070b57cec5SDimitry Andric   }
208e8d8bef9SDimitry Andric   return E;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
AddLiveExpr(llvm::ImmutableSet<const Expr * > & Set,llvm::ImmutableSet<const Expr * >::Factory & F,const Expr * E)211e8d8bef9SDimitry Andric static void AddLiveExpr(llvm::ImmutableSet<const Expr *> &Set,
212e8d8bef9SDimitry Andric                         llvm::ImmutableSet<const Expr *>::Factory &F,
213e8d8bef9SDimitry Andric                         const Expr *E) {
214e8d8bef9SDimitry Andric   Set = F.add(Set, LookThroughExpr(E));
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
Visit(Stmt * S)2170b57cec5SDimitry Andric void TransferFunctions::Visit(Stmt *S) {
2180b57cec5SDimitry Andric   if (observer)
2190b57cec5SDimitry Andric     observer->observeStmt(S, currentBlock, val);
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   StmtVisitor<TransferFunctions>::Visit(S);
2220b57cec5SDimitry Andric 
223e8d8bef9SDimitry Andric   if (const auto *E = dyn_cast<Expr>(S)) {
224e8d8bef9SDimitry Andric     val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
2250b57cec5SDimitry Andric   }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   // Mark all children expressions live.
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   switch (S->getStmtClass()) {
2300b57cec5SDimitry Andric     default:
2310b57cec5SDimitry Andric       break;
2320b57cec5SDimitry Andric     case Stmt::StmtExprClass: {
2330b57cec5SDimitry Andric       // For statement expressions, look through the compound statement.
2340b57cec5SDimitry Andric       S = cast<StmtExpr>(S)->getSubStmt();
2350b57cec5SDimitry Andric       break;
2360b57cec5SDimitry Andric     }
2370b57cec5SDimitry Andric     case Stmt::CXXMemberCallExprClass: {
2380b57cec5SDimitry Andric       // Include the implicit "this" pointer as being live.
2390b57cec5SDimitry Andric       CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
2400b57cec5SDimitry Andric       if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) {
241e8d8bef9SDimitry Andric         AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
2420b57cec5SDimitry Andric       }
2430b57cec5SDimitry Andric       break;
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric     case Stmt::ObjCMessageExprClass: {
2460b57cec5SDimitry Andric       // In calls to super, include the implicit "self" pointer as being live.
2470b57cec5SDimitry Andric       ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S);
2480b57cec5SDimitry Andric       if (CE->getReceiverKind() == ObjCMessageExpr::SuperInstance)
2490b57cec5SDimitry Andric         val.liveDecls = LV.DSetFact.add(val.liveDecls,
2500b57cec5SDimitry Andric                                         LV.analysisContext.getSelfDecl());
2510b57cec5SDimitry Andric       break;
2520b57cec5SDimitry Andric     }
2530b57cec5SDimitry Andric     case Stmt::DeclStmtClass: {
2540b57cec5SDimitry Andric       const DeclStmt *DS = cast<DeclStmt>(S);
2550b57cec5SDimitry Andric       if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
2560b57cec5SDimitry Andric         for (const VariableArrayType* VA = FindVA(VD->getType());
2570b57cec5SDimitry Andric              VA != nullptr; VA = FindVA(VA->getElementType())) {
258e8d8bef9SDimitry Andric           AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
2590b57cec5SDimitry Andric         }
2600b57cec5SDimitry Andric       }
2610b57cec5SDimitry Andric       break;
2620b57cec5SDimitry Andric     }
2630b57cec5SDimitry Andric     case Stmt::PseudoObjectExprClass: {
2640b57cec5SDimitry Andric       // A pseudo-object operation only directly consumes its result
2650b57cec5SDimitry Andric       // expression.
2660b57cec5SDimitry Andric       Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();
2670b57cec5SDimitry Andric       if (!child) return;
2680b57cec5SDimitry Andric       if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
2690b57cec5SDimitry Andric         child = OV->getSourceExpr();
2700b57cec5SDimitry Andric       child = child->IgnoreParens();
271e8d8bef9SDimitry Andric       val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
2720b57cec5SDimitry Andric       return;
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric     // FIXME: These cases eventually shouldn't be needed.
2760b57cec5SDimitry Andric     case Stmt::ExprWithCleanupsClass: {
2770b57cec5SDimitry Andric       S = cast<ExprWithCleanups>(S)->getSubExpr();
2780b57cec5SDimitry Andric       break;
2790b57cec5SDimitry Andric     }
2800b57cec5SDimitry Andric     case Stmt::CXXBindTemporaryExprClass: {
2810b57cec5SDimitry Andric       S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
2820b57cec5SDimitry Andric       break;
2830b57cec5SDimitry Andric     }
2840b57cec5SDimitry Andric     case Stmt::UnaryExprOrTypeTraitExprClass: {
2850b57cec5SDimitry Andric       // No need to unconditionally visit subexpressions.
2860b57cec5SDimitry Andric       return;
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric     case Stmt::IfStmtClass: {
2890b57cec5SDimitry Andric       // If one of the branches is an expression rather than a compound
2900b57cec5SDimitry Andric       // statement, it will be bad if we mark it as live at the terminator
2910b57cec5SDimitry Andric       // of the if-statement (i.e., immediately after the condition expression).
292e8d8bef9SDimitry Andric       AddLiveExpr(val.liveExprs, LV.ESetFact, cast<IfStmt>(S)->getCond());
2930b57cec5SDimitry Andric       return;
2940b57cec5SDimitry Andric     }
2950b57cec5SDimitry Andric     case Stmt::WhileStmtClass: {
2960b57cec5SDimitry Andric       // If the loop body is an expression rather than a compound statement,
2970b57cec5SDimitry Andric       // it will be bad if we mark it as live at the terminator of the loop
2980b57cec5SDimitry Andric       // (i.e., immediately after the condition expression).
299e8d8bef9SDimitry Andric       AddLiveExpr(val.liveExprs, LV.ESetFact, cast<WhileStmt>(S)->getCond());
3000b57cec5SDimitry Andric       return;
3010b57cec5SDimitry Andric     }
3020b57cec5SDimitry Andric     case Stmt::DoStmtClass: {
3030b57cec5SDimitry Andric       // If the loop body is an expression rather than a compound statement,
3040b57cec5SDimitry Andric       // it will be bad if we mark it as live at the terminator of the loop
3050b57cec5SDimitry Andric       // (i.e., immediately after the condition expression).
306e8d8bef9SDimitry Andric       AddLiveExpr(val.liveExprs, LV.ESetFact, cast<DoStmt>(S)->getCond());
3070b57cec5SDimitry Andric       return;
3080b57cec5SDimitry Andric     }
3090b57cec5SDimitry Andric     case Stmt::ForStmtClass: {
3100b57cec5SDimitry Andric       // If the loop body is an expression rather than a compound statement,
3110b57cec5SDimitry Andric       // it will be bad if we mark it as live at the terminator of the loop
3120b57cec5SDimitry Andric       // (i.e., immediately after the condition expression).
313e8d8bef9SDimitry Andric       AddLiveExpr(val.liveExprs, LV.ESetFact, cast<ForStmt>(S)->getCond());
3140b57cec5SDimitry Andric       return;
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric 
319e8d8bef9SDimitry Andric   // HACK + FIXME: What is this? One could only guess that this is an attempt to
320e8d8bef9SDimitry Andric   // fish for live values, for example, arguments from a call expression.
321e8d8bef9SDimitry Andric   // Maybe we could take inspiration from UninitializedVariable analysis?
3220b57cec5SDimitry Andric   for (Stmt *Child : S->children()) {
323e8d8bef9SDimitry Andric     if (const auto *E = dyn_cast_or_null<Expr>(Child))
324e8d8bef9SDimitry Andric       AddLiveExpr(val.liveExprs, LV.ESetFact, E);
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
writeShouldKill(const VarDecl * VD)3280b57cec5SDimitry Andric static bool writeShouldKill(const VarDecl *VD) {
3290b57cec5SDimitry Andric   return VD && !VD->getType()->isReferenceType() &&
3300b57cec5SDimitry Andric     !isAlwaysAlive(VD);
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
VisitBinaryOperator(BinaryOperator * B)3330b57cec5SDimitry Andric void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
334fe6060f1SDimitry Andric   if (LV.killAtAssign && B->getOpcode() == BO_Assign) {
335fe6060f1SDimitry Andric     if (const auto *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {
336fe6060f1SDimitry Andric       LV.inAssignment[DR] = 1;
337fe6060f1SDimitry Andric     }
338fe6060f1SDimitry Andric   }
3390b57cec5SDimitry Andric   if (B->isAssignmentOp()) {
3400b57cec5SDimitry Andric     if (!LV.killAtAssign)
3410b57cec5SDimitry Andric       return;
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric     // Assigning to a variable?
3440b57cec5SDimitry Andric     Expr *LHS = B->getLHS()->IgnoreParens();
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric     if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
3470b57cec5SDimitry Andric       const Decl* D = DR->getDecl();
3480b57cec5SDimitry Andric       bool Killed = false;
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric       if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
3510b57cec5SDimitry Andric         Killed = !BD->getType()->isReferenceType();
352972a253aSDimitry Andric         if (Killed) {
353972a253aSDimitry Andric           if (const auto *HV = BD->getHoldingVar())
354972a253aSDimitry Andric             val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
355972a253aSDimitry Andric 
3560b57cec5SDimitry Andric           val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
357972a253aSDimitry Andric         }
3580b57cec5SDimitry Andric       } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
3590b57cec5SDimitry Andric         Killed = writeShouldKill(VD);
3600b57cec5SDimitry Andric         if (Killed)
3610b57cec5SDimitry Andric           val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric       }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric       if (Killed && observer)
3660b57cec5SDimitry Andric         observer->observerKill(DR);
3670b57cec5SDimitry Andric     }
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
VisitBlockExpr(BlockExpr * BE)3710b57cec5SDimitry Andric void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
3720b57cec5SDimitry Andric   for (const VarDecl *VD :
3730b57cec5SDimitry Andric        LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
3740b57cec5SDimitry Andric     if (isAlwaysAlive(VD))
3750b57cec5SDimitry Andric       continue;
3760b57cec5SDimitry Andric     val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
3770b57cec5SDimitry Andric   }
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
VisitDeclRefExpr(DeclRefExpr * DR)3800b57cec5SDimitry Andric void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
3810b57cec5SDimitry Andric   const Decl* D = DR->getDecl();
3820b57cec5SDimitry Andric   bool InAssignment = LV.inAssignment[DR];
3830b57cec5SDimitry Andric   if (const auto *BD = dyn_cast<BindingDecl>(D)) {
384972a253aSDimitry Andric     if (!InAssignment) {
385972a253aSDimitry Andric       if (const auto *HV = BD->getHoldingVar())
386972a253aSDimitry Andric         val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
387972a253aSDimitry Andric 
3880b57cec5SDimitry Andric       val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
389972a253aSDimitry Andric     }
3900b57cec5SDimitry Andric   } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
3910b57cec5SDimitry Andric     if (!InAssignment && !isAlwaysAlive(VD))
3920b57cec5SDimitry Andric       val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
VisitDeclStmt(DeclStmt * DS)3960b57cec5SDimitry Andric void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
3970b57cec5SDimitry Andric   for (const auto *DI : DS->decls()) {
3980b57cec5SDimitry Andric     if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
399972a253aSDimitry Andric       for (const auto *BD : DD->bindings()) {
400972a253aSDimitry Andric         if (const auto *HV = BD->getHoldingVar())
401972a253aSDimitry Andric           val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
402972a253aSDimitry Andric 
4030b57cec5SDimitry Andric         val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
404972a253aSDimitry Andric       }
405972a253aSDimitry Andric 
406972a253aSDimitry Andric       // When a bindig to a tuple-like structure is created, the HoldingVar
407972a253aSDimitry Andric       // initializers have a DeclRefExpr to the DecompositionDecl.
408972a253aSDimitry Andric       val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
4090b57cec5SDimitry Andric     } else if (const auto *VD = dyn_cast<VarDecl>(DI)) {
4100b57cec5SDimitry Andric       if (!isAlwaysAlive(VD))
4110b57cec5SDimitry Andric         val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
4120b57cec5SDimitry Andric     }
4130b57cec5SDimitry Andric   }
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
VisitObjCForCollectionStmt(ObjCForCollectionStmt * OS)4160b57cec5SDimitry Andric void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
4170b57cec5SDimitry Andric   // Kill the iteration variable.
4180b57cec5SDimitry Andric   DeclRefExpr *DR = nullptr;
4190b57cec5SDimitry Andric   const VarDecl *VD = nullptr;
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   Stmt *element = OS->getElement();
4220b57cec5SDimitry Andric   if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
4230b57cec5SDimitry Andric     VD = cast<VarDecl>(DS->getSingleDecl());
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric   else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
4260b57cec5SDimitry Andric     VD = cast<VarDecl>(DR->getDecl());
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   if (VD) {
4300b57cec5SDimitry Andric     val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
4310b57cec5SDimitry Andric     if (observer && DR)
4320b57cec5SDimitry Andric       observer->observerKill(DR);
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric void TransferFunctions::
VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr * UE)4370b57cec5SDimitry Andric VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
4380b57cec5SDimitry Andric {
4390b57cec5SDimitry Andric   // While sizeof(var) doesn't technically extend the liveness of 'var', it
4400b57cec5SDimitry Andric   // does extent the liveness of metadata if 'var' is a VariableArrayType.
4410b57cec5SDimitry Andric   // We handle that special case here.
4420b57cec5SDimitry Andric   if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
4430b57cec5SDimitry Andric     return;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   const Expr *subEx = UE->getArgumentExpr();
4460b57cec5SDimitry Andric   if (subEx->getType()->isVariableArrayType()) {
4470b57cec5SDimitry Andric     assert(subEx->isLValue());
448e8d8bef9SDimitry Andric     val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
VisitUnaryOperator(UnaryOperator * UO)4520b57cec5SDimitry Andric void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
4530b57cec5SDimitry Andric   // Treat ++/-- as a kill.
4540b57cec5SDimitry Andric   // Note we don't actually have to do anything if we don't have an observer,
4550b57cec5SDimitry Andric   // since a ++/-- acts as both a kill and a "use".
4560b57cec5SDimitry Andric   if (!observer)
4570b57cec5SDimitry Andric     return;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   switch (UO->getOpcode()) {
4600b57cec5SDimitry Andric   default:
4610b57cec5SDimitry Andric     return;
4620b57cec5SDimitry Andric   case UO_PostInc:
4630b57cec5SDimitry Andric   case UO_PostDec:
4640b57cec5SDimitry Andric   case UO_PreInc:
4650b57cec5SDimitry Andric   case UO_PreDec:
4660b57cec5SDimitry Andric     break;
4670b57cec5SDimitry Andric   }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   if (auto *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
4700b57cec5SDimitry Andric     const Decl *D = DR->getDecl();
4710b57cec5SDimitry Andric     if (isa<VarDecl>(D) || isa<BindingDecl>(D)) {
4720b57cec5SDimitry Andric       // Treat ++/-- as a kill.
4730b57cec5SDimitry Andric       observer->observerKill(DR);
4740b57cec5SDimitry Andric     }
4750b57cec5SDimitry Andric   }
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric LiveVariables::LivenessValues
runOnBlock(const CFGBlock * block,LiveVariables::LivenessValues val,LiveVariables::Observer * obs)4790b57cec5SDimitry Andric LiveVariablesImpl::runOnBlock(const CFGBlock *block,
4800b57cec5SDimitry Andric                               LiveVariables::LivenessValues val,
4810b57cec5SDimitry Andric                               LiveVariables::Observer *obs) {
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   TransferFunctions TF(*this, val, obs, block);
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   // Visit the terminator (if any).
4860b57cec5SDimitry Andric   if (const Stmt *term = block->getTerminatorStmt())
4870b57cec5SDimitry Andric     TF.Visit(const_cast<Stmt*>(term));
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   // Apply the transfer function for all Stmts in the block.
4900b57cec5SDimitry Andric   for (CFGBlock::const_reverse_iterator it = block->rbegin(),
4910b57cec5SDimitry Andric        ei = block->rend(); it != ei; ++it) {
4920b57cec5SDimitry Andric     const CFGElement &elem = *it;
4930b57cec5SDimitry Andric 
494*bdd1243dSDimitry Andric     if (std::optional<CFGAutomaticObjDtor> Dtor =
4950b57cec5SDimitry Andric             elem.getAs<CFGAutomaticObjDtor>()) {
4960b57cec5SDimitry Andric       val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());
4970b57cec5SDimitry Andric       continue;
4980b57cec5SDimitry Andric     }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric     if (!elem.getAs<CFGStmt>())
5010b57cec5SDimitry Andric       continue;
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric     const Stmt *S = elem.castAs<CFGStmt>().getStmt();
5040b57cec5SDimitry Andric     TF.Visit(const_cast<Stmt*>(S));
5050b57cec5SDimitry Andric     stmtsToLiveness[S] = val;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric   return val;
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
runOnAllBlocks(LiveVariables::Observer & obs)5100b57cec5SDimitry Andric void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
5110b57cec5SDimitry Andric   const CFG *cfg = getImpl(impl).analysisContext.getCFG();
5120b57cec5SDimitry Andric   for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
5130b57cec5SDimitry Andric     getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
LiveVariables(void * im)5160b57cec5SDimitry Andric LiveVariables::LiveVariables(void *im) : impl(im) {}
5170b57cec5SDimitry Andric 
~LiveVariables()5180b57cec5SDimitry Andric LiveVariables::~LiveVariables() {
5190b57cec5SDimitry Andric   delete (LiveVariablesImpl*) impl;
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric 
5225ffd83dbSDimitry Andric std::unique_ptr<LiveVariables>
computeLiveness(AnalysisDeclContext & AC,bool killAtAssign)5235ffd83dbSDimitry Andric LiveVariables::computeLiveness(AnalysisDeclContext &AC, bool killAtAssign) {
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   // No CFG?  Bail out.
5260b57cec5SDimitry Andric   CFG *cfg = AC.getCFG();
5270b57cec5SDimitry Andric   if (!cfg)
5280b57cec5SDimitry Andric     return nullptr;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // The analysis currently has scalability issues for very large CFGs.
5310b57cec5SDimitry Andric   // Bail out if it looks too large.
5320b57cec5SDimitry Andric   if (cfg->getNumBlockIDs() > 300000)
5330b57cec5SDimitry Andric     return nullptr;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   // Construct the dataflow worklist.  Enqueue the exit block as the
5380b57cec5SDimitry Andric   // start of the analysis.
5395ffd83dbSDimitry Andric   BackwardDataflowWorklist worklist(*cfg, AC);
5400b57cec5SDimitry Andric   llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   // FIXME: we should enqueue using post order.
543fe6060f1SDimitry Andric   for (const CFGBlock *B : cfg->nodes()) {
544fe6060f1SDimitry Andric     worklist.enqueueBlock(B);
5450b57cec5SDimitry Andric   }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   while (const CFGBlock *block = worklist.dequeue()) {
5480b57cec5SDimitry Andric     // Determine if the block's end value has changed.  If not, we
5490b57cec5SDimitry Andric     // have nothing left to do for this block.
5500b57cec5SDimitry Andric     LivenessValues &prevVal = LV->blocksEndToLiveness[block];
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric     // Merge the values of all successor blocks.
5530b57cec5SDimitry Andric     LivenessValues val;
5540b57cec5SDimitry Andric     for (CFGBlock::const_succ_iterator it = block->succ_begin(),
5550b57cec5SDimitry Andric                                        ei = block->succ_end(); it != ei; ++it) {
5560b57cec5SDimitry Andric       if (const CFGBlock *succ = *it) {
5570b57cec5SDimitry Andric         val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
5580b57cec5SDimitry Andric       }
5590b57cec5SDimitry Andric     }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     if (!everAnalyzedBlock[block->getBlockID()])
5620b57cec5SDimitry Andric       everAnalyzedBlock[block->getBlockID()] = true;
5630b57cec5SDimitry Andric     else if (prevVal.equals(val))
5640b57cec5SDimitry Andric       continue;
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric     prevVal = val;
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric     // Update the dataflow value for the start of this block.
5690b57cec5SDimitry Andric     LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric     // Enqueue the value to the predecessors.
5720b57cec5SDimitry Andric     worklist.enqueuePredecessors(block);
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric 
5755ffd83dbSDimitry Andric   return std::unique_ptr<LiveVariables>(new LiveVariables(LV));
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
dumpBlockLiveness(const SourceManager & M)5780b57cec5SDimitry Andric void LiveVariables::dumpBlockLiveness(const SourceManager &M) {
5790b57cec5SDimitry Andric   getImpl(impl).dumpBlockLiveness(M);
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
dumpBlockLiveness(const SourceManager & M)5820b57cec5SDimitry Andric void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
5830b57cec5SDimitry Andric   std::vector<const CFGBlock *> vec;
5840b57cec5SDimitry Andric   for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
5850b57cec5SDimitry Andric        it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
5860b57cec5SDimitry Andric        it != ei; ++it) {
5870b57cec5SDimitry Andric     vec.push_back(it->first);
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric   llvm::sort(vec, [](const CFGBlock *A, const CFGBlock *B) {
5900b57cec5SDimitry Andric     return A->getBlockID() < B->getBlockID();
5910b57cec5SDimitry Andric   });
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   std::vector<const VarDecl*> declVec;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   for (std::vector<const CFGBlock *>::iterator
5960b57cec5SDimitry Andric         it = vec.begin(), ei = vec.end(); it != ei; ++it) {
5970b57cec5SDimitry Andric     llvm::errs() << "\n[ B" << (*it)->getBlockID()
5980b57cec5SDimitry Andric                  << " (live variables at block exit) ]\n";
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric     LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
6010b57cec5SDimitry Andric     declVec.clear();
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric     for (llvm::ImmutableSet<const VarDecl *>::iterator si =
6040b57cec5SDimitry Andric           vals.liveDecls.begin(),
6050b57cec5SDimitry Andric           se = vals.liveDecls.end(); si != se; ++si) {
6060b57cec5SDimitry Andric       declVec.push_back(*si);
6070b57cec5SDimitry Andric     }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric     llvm::sort(declVec, [](const Decl *A, const Decl *B) {
6100b57cec5SDimitry Andric       return A->getBeginLoc() < B->getBeginLoc();
6110b57cec5SDimitry Andric     });
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric     for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
6140b57cec5SDimitry Andric          de = declVec.end(); di != de; ++di) {
6150b57cec5SDimitry Andric       llvm::errs() << " " << (*di)->getDeclName().getAsString()
6160b57cec5SDimitry Andric                    << " <";
6170b57cec5SDimitry Andric       (*di)->getLocation().print(llvm::errs(), M);
6180b57cec5SDimitry Andric       llvm::errs() << ">\n";
6190b57cec5SDimitry Andric     }
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric   llvm::errs() << "\n";
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
dumpExprLiveness(const SourceManager & M)624e8d8bef9SDimitry Andric void LiveVariables::dumpExprLiveness(const SourceManager &M) {
625e8d8bef9SDimitry Andric   getImpl(impl).dumpExprLiveness(M);
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
dumpExprLiveness(const SourceManager & M)628e8d8bef9SDimitry Andric void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) {
6290b57cec5SDimitry Andric   // Don't iterate over blockEndsToLiveness directly because it's not sorted.
630e8d8bef9SDimitry Andric   for (const CFGBlock *B : *analysisContext.getCFG()) {
6310b57cec5SDimitry Andric 
632e8d8bef9SDimitry Andric     llvm::errs() << "\n[ B" << B->getBlockID()
633e8d8bef9SDimitry Andric                  << " (live expressions at block exit) ]\n";
634e8d8bef9SDimitry Andric     for (const Expr *E : blocksEndToLiveness[B].liveExprs) {
6350b57cec5SDimitry Andric       llvm::errs() << "\n";
636e8d8bef9SDimitry Andric       E->dump();
6370b57cec5SDimitry Andric     }
6380b57cec5SDimitry Andric     llvm::errs() << "\n";
6390b57cec5SDimitry Andric   }
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
getTag()6420b57cec5SDimitry Andric const void *LiveVariables::getTag() { static int x; return &x; }
getTag()6430b57cec5SDimitry Andric const void *RelaxedLiveVariables::getTag() { static int x; return &x; }
644