diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 9e9972ac49..40d1dff446 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -30,6 +30,7 @@ #include "phasar/Utils/Logger.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constant.h" @@ -629,26 +630,19 @@ class IDEInstInteractionAnalysisT // variables using generalized initial seeds // Generate zero value at the entry points - Seeds.addSeed(SP, this->getZeroValue(), bottomElement()); + Seeds.addSeed(SP, this->getZeroValue(), Bottom{}); // Generate formal parameters of entry points, e.g. main(). Formal // parameters will otherwise cause trouble by overriding alloca // instructions without being valid data-flow facts themselves. for (const auto &Arg : SP->getFunction()->args()) { - Seeds.addSeed(SP, &Arg, Bottom{}); + Seeds.addSeed(SP, &Arg, BitVectorSet()); } // Generate all global variables using generalized initial seeds for (const auto &G : this->IRDB->getModule()->globals()) { if (const auto *GV = llvm::dyn_cast(&G)) { - l_t InitialValues = BitVectorSet(); - std::set EdgeFacts; - if (EdgeFactGen) { - EdgeFacts = EdgeFactGen(GV); - // fill BitVectorSet - InitialValues = - BitVectorSet(EdgeFacts.begin(), EdgeFacts.end()); - } - Seeds.addSeed(SP, GV, InitialValues); + l_t InitialValues = bvSetFrom(invoke_or_default(EdgeFactGen, GV)); + Seeds.addSeed(SP, GV, std::move(InitialValues)); } } }); @@ -691,7 +685,12 @@ class IDEInstInteractionAnalysisT if (SuccNode == Store->getPointerOperand() || PT.isInReachableAllocationSites(Store->getPointerOperand(), SuccNode, true, Store)) { - return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts); + if (isZeroValue(CurrNode)) { + return IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(UserEdgeFacts)); + } + return IIAAAddLabelsEFCache.createEdgeFunction( + std::move(UserEdgeFacts)); } } @@ -709,7 +708,7 @@ class IDEInstInteractionAnalysisT // v // y // - if ((CurrNode == SuccNode) && CurrNode == Store->getPointerOperand()) { + if (CurrNode == SuccNode && CurrNode == Store->getPointerOperand()) { // y obtains its value(s) from its original allocation and the store // instruction under analysis. IF_LOG_ENABLED({ @@ -722,7 +721,8 @@ class IDEInstInteractionAnalysisT PHASAR_LOG_LEVEL(DFADEBUG, '\n'); }); // obtain label from the original allocation - return IIAAKillOrReplaceEFCache.createEdgeFunction(UserEdgeFacts); + return IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(UserEdgeFacts)); } } else { @@ -800,7 +800,11 @@ class IDEInstInteractionAnalysisT // We generate Curr in this instruction, so we have to annotate it with // edge labels - return IIAAAddLabelsEFCache.createEdgeFunction(UserEdgeFacts); + if (isZeroValue(CurrNode)) { + return IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(UserEdgeFacts)); + } + return IIAAAddLabelsEFCache.createEdgeFunction(std::move(UserEdgeFacts)); } // Otherwise stick to identity. @@ -835,7 +839,7 @@ class IDEInstInteractionAnalysisT } } if (isZeroValue(SrcNode) && SRetParams.count(DestNode)) { - return IIAAAddLabelsEFCache.createEdgeFunction(); + return IIAAKillOrReplaceEFCache.createEdgeFunction(); } // Everything else can be passed as identity. return EdgeIdentity{}; @@ -863,14 +867,8 @@ class IDEInstInteractionAnalysisT if (const auto *CD = llvm::dyn_cast(Ret->getReturnValue())) { // Check if the user has registered a fact generator function - l_t UserEdgeFacts = BitVectorSet(); - std::set EdgeFacts; - if (EdgeFactGen) { - EdgeFacts = EdgeFactGen(ExitInst); - // fill BitVectorSet - UserEdgeFacts = BitVectorSet(EdgeFacts.begin(), EdgeFacts.end()); - } - return IIAAAddLabelsEFCache.createEdgeFunction( + l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, ExitInst)); + return IIAAKillOrReplaceEFCache.createEdgeFunction( std::move(UserEdgeFacts)); } } @@ -883,34 +881,29 @@ class IDEInstInteractionAnalysisT d_t RetSiteNode, llvm::ArrayRef Callees) override { // Check if the user has registered a fact generator function - l_t UserEdgeFacts = BitVectorSet(); - std::set EdgeFacts; - if (EdgeFactGen) { - EdgeFacts = EdgeFactGen(CallSite); - // fill BitVectorSet - UserEdgeFacts = BitVectorSet(EdgeFacts.begin(), EdgeFacts.end()); - } + l_t UserEdgeFacts = bvSetFrom(invoke_or_default(EdgeFactGen, CallSite)); + // Model call to heap allocating functions (new, new[], malloc, etc.) -- // only model direct calls, though. if (Callees.size() == 1) { - for (const auto *Callee : Callees) { - if (this->ICF->isHeapAllocatingFunction(Callee)) { - // Let H be a heap allocating function. - // - // 0 --> x - // - // Edge function: - // - // 0 - // \ + const auto *Callee = Callees.front(); + + if (this->ICF->isHeapAllocatingFunction(Callee)) { + // Let H be a heap allocating function. + // + // 0 --> x + // + // Edge function: + // + // 0 + // \ // %i = call H \ \x.x \cup { commit of('%i = call H') } - // v - // i - // - if (isZeroValue(CallNode) && RetSiteNode == CallSite) { - return IIAAAddLabelsEFCache.createEdgeFunction( - std::move(UserEdgeFacts)); - } + // v + // i + // + if (isZeroValue(CallNode) && RetSiteNode == CallSite) { + return IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(UserEdgeFacts)); } } } @@ -944,10 +937,6 @@ class IDEInstInteractionAnalysisT return nullptr; } - inline l_t topElement() override { return Top{}; } - - inline l_t bottomElement() override { return Bottom{}; } - inline l_t join(l_t Lhs, l_t Rhs) override { return joinImpl(Lhs, Rhs); } // Provide some handy helper edge functions to improve reuse. @@ -956,7 +945,7 @@ class IDEInstInteractionAnalysisT // others). struct IIAAKillOrReplaceEF { using l_t = typename AnalysisDomainTy::l_t; - l_t Replacement{}; + l_t Replacement = BitVectorSet(); l_t computeTarget(ByConstRef /* Src */) const { return Replacement; } @@ -972,27 +961,13 @@ class IDEInstInteractionAnalysisT "IIAAKillOrReplaceEF is too large for SOO"); if (auto *AD = llvm::dyn_cast(SecondFunction)) { - auto ADCache = - SecondFunction.template getCacheOrNull(); - assert(ADCache != nullptr); - if (This->isKillAll()) { - return ADCache->createEdgeFunction(*AD); - } auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data); - return ADCache->createEdgeFunction(std::move(Union)); + return Cache->createEdgeFunction(std::move(Union)); } if (auto *KR = llvm::dyn_cast(SecondFunction)) { - if (This->isKillAll()) { - return Cache->createEdgeFunction(*KR); - } - if (KR->isKillAll()) { - return SecondFunction; - } - auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement, - KR->Replacement); - return Cache->createEdgeFunction(std::move(Union)); + return SecondFunction; } llvm::report_fatal_error( "found unexpected edge function in 'IIAAKillOrReplaceEF'"); @@ -1033,6 +1008,8 @@ class IDEInstInteractionAnalysisT return Replacement == Other.Replacement; } + [[nodiscard]] bool isConstant() const noexcept { return true; } + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const IIAAKillOrReplaceEF &EF) { OS << "EF: (IIAAKillOrReplaceEF)<->"; @@ -1061,7 +1038,7 @@ class IDEInstInteractionAnalysisT // add all labels provided by Data. struct IIAAAddLabelsEF { using l_t = typename AnalysisDomainTy::l_t; - l_t Data{}; + l_t Data = BitVectorSet(); l_t computeTarget(ByConstRef Src) const { return IDEInstInteractionAnalysisT::joinImpl(Src, Data); @@ -1083,7 +1060,7 @@ class IDEInstInteractionAnalysisT return Cache->createEdgeFunction(std::move(Union)); } if (auto *KR = llvm::dyn_cast(SecondFunction)) { - return Cache->createEdgeFunction(KR->Replacement); + return SecondFunction; } llvm::report_fatal_error( "found unexpected edge function in 'IIAAAddLabelsEF'"); @@ -1214,9 +1191,8 @@ class IDEInstInteractionAnalysisT } protected: - static inline bool isZeroValueImpl(d_t d) { - return LLVMZeroValue::isLLVMZeroValue(d); - } + // NOLINTNEXTLINE(readability-identifier-naming) + static constexpr auto isZeroValueImpl = LLVMZeroValue::isLLVMZeroValue; static void printEdgeFactImpl(llvm::raw_ostream &OS, ByConstRef EdgeFact) { @@ -1244,10 +1220,10 @@ class IDEInstInteractionAnalysisT } static inline l_t joinImpl(ByConstRef Lhs, ByConstRef Rhs) { - if (Lhs.isTop() || Lhs.isBottom()) { + if (Lhs.isTop() || Rhs.isBottom()) { return Rhs; } - if (Rhs.isTop() || Rhs.isBottom()) { + if (Rhs.isTop() || Lhs.isBottom()) { return Lhs; } const auto &LhsSet = std::get>(Lhs); @@ -1270,7 +1246,7 @@ class IDEInstInteractionAnalysisT // at some point. Therefore, we only care for the variables and their // associated values and ignore at which point a variable may holds as a // data-flow fact. - const auto Variable = Result.getColumnKey(); + const auto &Variable = Result.getColumnKey(); const auto &Value = Result.getValue(); // skip result entry if variable is not in the set of all variables if (Variables.find(Variable) == Variables.end()) {