From 1f0596551ed0b1740f08be97311c1a3180a62ea9 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 5 Jan 2022 11:37:12 +0100 Subject: [PATCH 1/7] several updates --- .../DataFlowSolver/IfdsIde/LLVMZeroValue.h | 9 +- .../Problems/IDELinearConstantAnalysis.cpp | 495 ++++++++---------- .../IDELinearConstantAnalysisTest.cpp | 18 +- .../IDELinearConstantAnalysis_DotTest.cpp | 2 + 4 files changed, 236 insertions(+), 288 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h index 378a08afd6..5be941068b 100644 --- a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h +++ b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/LLVMZeroValue.h @@ -68,13 +68,8 @@ class LLVMZeroValue : public llvm::GlobalVariable { return LLVMZeroValueInternalName; } - bool isLLVMZeroValue(const llvm::Value *V) const { - if (V && V->hasName()) { - // checks if V's name start with "zero_value" - return V->getName().find(LLVMZeroValueInternalName) != - llvm::StringRef::npos; - } - return false; + static bool isLLVMZeroValue(const llvm::Value *V) { + return V == getInstance(); } // Do not specify a destructor (at all)! diff --git a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 41faaef951..03926c2899 100644 --- a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -9,6 +9,7 @@ // #include #include +#include #include #include "llvm/IR/AbstractCallSite.h" @@ -31,11 +32,11 @@ #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h" #include "phasar/PhasarLLVM/Pointer/LLVMPointsToInfo.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarPass/Options.h" #include "phasar/Utils/LLVMIRToSrc.h" #include "phasar/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" -using namespace std; using namespace psr; namespace psr { @@ -45,10 +46,10 @@ unsigned IDELinearConstantAnalysis::CurrLCAIDId = 0; // NOLINT unsigned IDELinearConstantAnalysis::CurrBinaryId = 0; // NOLINT const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = - numeric_limits::min(); + std::numeric_limits::min(); const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BOTTOM = - numeric_limits::max(); + std::numeric_limits::max(); IDELinearConstantAnalysis::IDELinearConstantAnalysis( const ProjectIRDB *IRDB, const LLVMTypeHierarchy *TH, @@ -60,99 +61,83 @@ IDELinearConstantAnalysis::IDELinearConstantAnalysis( } IDELinearConstantAnalysis::~IDELinearConstantAnalysis() { - IDELinearConstantAnalysis::CurrGenConstantId = 0; - IDELinearConstantAnalysis::CurrLCAIDId = 0; - IDELinearConstantAnalysis::CurrBinaryId = 0; + CurrGenConstantId = 0; + CurrLCAIDId = 0; + CurrBinaryId = 0; } // Start formulating our analysis by specifying the parts required for IFDS IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getNormalFlowFunction( - IDELinearConstantAnalysis::n_t Curr, - IDELinearConstantAnalysis::n_t /*Succ*/) { +IDELinearConstantAnalysis::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) { if (const auto *Alloca = llvm::dyn_cast(Curr)) { if (Alloca->getAllocatedType()->isIntegerTy()) { - return make_shared>(Alloca, - getZeroValue()); + return std::make_shared>(Alloca, getZeroValue()); } } // Check store instructions. Store instructions override previous value // of their pointer operand, i.e., kills previous fact (= pointer operand). if (const auto *Store = llvm::dyn_cast(Curr)) { - IDELinearConstantAnalysis::d_t ValueOp = Store->getValueOperand(); + d_t ValueOp = Store->getValueOperand(); // Case I: Storing a constant integer. if (llvm::isa(ValueOp)) { // return Identity::getInstance(); - return make_shared>( - Store, [this](IDELinearConstantAnalysis::d_t Source) { - return Source == getZeroValue(); - }); + return std::make_shared>( + Store, [this](d_t Source) { return Source == getZeroValue(); }); } // Case II: Storing an integer typed value. if (ValueOp->getType()->isIntegerTy()) { - return make_shared>( - Store, [Store](IDELinearConstantAnalysis::d_t Source) { - return Source == Store->getValueOperand(); - }); + return std::make_shared>( + Store, + [Store](d_t Source) { return Source == Store->getValueOperand(); }); } } // check load instructions if (const auto *Load = llvm::dyn_cast(Curr)) { // only consider i32 load if (Load->getPointerOperandType()->getPointerElementType()->isIntegerTy()) { - return make_shared>( - Load, [Load](IDELinearConstantAnalysis::d_t Source) { - return Source == Load->getPointerOperand(); - }); + return std::make_shared>(Load, [Load](d_t Source) { + return Source == Load->getPointerOperand(); + }); } } // check for binary operations: add, sub, mul, udiv/sdiv, urem/srem if (llvm::isa(Curr)) { auto *Lop = Curr->getOperand(0); auto *Rop = Curr->getOperand(1); - return make_shared>( - Curr, [this, Lop, Rop](IDELinearConstantAnalysis::d_t Source) { - return (Lop == Source && llvm::isa(Rop)) || - (Rop == Source && llvm::isa(Lop)) || - (Source == getZeroValue() && - !llvm::isa(Lop) && - !llvm::isa(Rop)); - }); + return std::make_shared>(Curr, [this, Lop, Rop](d_t Source) { + /// Intentionally include nonlinear operations here for being able to + /// explicitly set them to BOTTOM in the edge function + return (Lop == Source) || (Rop == Source) || + (isZeroValue(Source) && llvm::isa(Lop) && + llvm::isa(Rop)); + }); } - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getCallFlowFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::f_t DestFun) { - - // std::cout << "found call at: " << llvmIRToString(CallSite) << '\n'; - +IDELinearConstantAnalysis::getCallFlowFunction(n_t CallSite, f_t DestFun) { // Map the actual parameters into the formal parameters if (const auto *CS = llvm::dyn_cast(CallSite)) { struct LCAFF : FlowFunction { - vector Actuals; - vector Formals; + std::vector Actuals; + std::vector Formals; const llvm::Function *DestFun; - LCAFF(const llvm::CallBase *CallSite, - IDELinearConstantAnalysis::f_t DestFun) - : DestFun(DestFun) { - // Set up the actual parameters + LCAFF(const llvm::CallBase *CallSite, f_t DestFun) : DestFun(DestFun) { + // std::set up the actual parameters for (unsigned Idx = 0; Idx < CallSite->getNumArgOperands(); ++Idx) { Actuals.push_back(CallSite->getArgOperand(Idx)); } - // Set up the formal parameters + // std::set up the formal parameters for (unsigned Idx = 0; Idx < DestFun->arg_size(); ++Idx) { Formals.push_back(getNthFunctionArgument(DestFun, Idx)); } } - set - computeTargets(IDELinearConstantAnalysis::d_t Source) override { + std::set computeTargets(d_t Source) override { // std::cout << "call call-ff with: " << llvmIRToString(Source) << '\n'; - set Res; + std::set Res; for (unsigned Idx = 0; Idx < Actuals.size(); ++Idx) { if (Source == Actuals[Idx]) { // Check for C-style varargs: idx >= destFun->arg_size() @@ -185,13 +170,13 @@ IDELinearConstantAnalysis::getCallFlowFunction( } // Special case: Check if function is called with integer literals as // parameter (in case of varargs ignore) - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (LLVMZeroValue::isLLVMZeroValue(Source) && Idx < DestFun->arg_size() && llvm::isa(Actuals[Idx])) { Res.insert(Formals[Idx]); // corresponding formal } } - if (!LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (!LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(Source)) { Res.insert(Source); } @@ -200,89 +185,76 @@ IDELinearConstantAnalysis::getCallFlowFunction( }; if (!DestFun->isDeclaration()) { - return make_shared(CS, DestFun); + return std::make_shared(CS, DestFun); } } // Pass everything else as identity - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getRetFlowFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::f_t /*CalleeFun*/, - IDELinearConstantAnalysis::n_t ExitInst, - IDELinearConstantAnalysis::n_t /*RetSite*/) { +IDELinearConstantAnalysis::getRetFlowFunction(n_t CallSite, f_t /*CalleeFun*/, + n_t ExitInst, n_t /*RetSite*/) { // Handle the case: %x = call i32 ... if (CallSite->getType()->isIntegerTy()) { const auto *Return = llvm::dyn_cast(ExitInst); auto *ReturnValue = Return ? Return->getReturnValue() : nullptr; if (ReturnValue) { - struct LCAFF : FlowFunction { - IDELinearConstantAnalysis::n_t CallSite; - IDELinearConstantAnalysis::d_t ReturnValue; - LCAFF(IDELinearConstantAnalysis::n_t CS, - IDELinearConstantAnalysis::d_t RetVal) - : CallSite(CS), ReturnValue(RetVal) {} - set - computeTargets(IDELinearConstantAnalysis::d_t Source) override { - set Res; + struct LCAFF : FlowFunction { + n_t CallSite; + d_t ReturnValue; + LCAFF(n_t CS, d_t RetVal) : CallSite(CS), ReturnValue(RetVal) {} + std::set computeTargets(d_t Source) override { + std::set Res; // Collect return value fact if (Source == ReturnValue) { Res.insert(CallSite); } // Return value is integer literal - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(ReturnValue)) { Res.insert(CallSite); } - if (!LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (!LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(Source)) { Res.insert(Source); } return Res; } }; - return make_shared(CallSite, ReturnValue); + return std::make_shared(CallSite, ReturnValue); } } // All other facts except GlobalVariables are killed at this point - return make_shared>( - [](IDELinearConstantAnalysis::d_t Source) { - return !llvm::isa(Source); - }); + return std::make_shared>( + [](d_t Source) { return !llvm::isa(Source); }); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getCallToRetFlowFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, set Callees) { +IDELinearConstantAnalysis::getCallToRetFlowFunction(n_t /*CallSite*/, + n_t /*RetSite*/, + std::set Callees) { for (const auto *Callee : Callees) { if (!ICF->getStartPointsOf(Callee).empty()) { - return make_shared>( - [this](IDELinearConstantAnalysis::d_t Source) { - return !isZeroValue(Source) && - llvm::isa(Source); - }); + return std::make_shared>([this](d_t Source) { + return !isZeroValue(Source) && llvm::isa(Source); + }); } } - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getSummaryFlowFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::f_t /*DestFun*/) { +IDELinearConstantAnalysis::getSummaryFlowFunction(n_t /*CallSite*/, + f_t /*DestFun*/) { return nullptr; } InitialSeeds IDELinearConstantAnalysis::initialSeeds() { - InitialSeeds - Seeds; + InitialSeeds Seeds; // The analysis' entry points std::set EntryPointFuns; @@ -291,7 +263,7 @@ IDELinearConstantAnalysis::initialSeeds() { EntryPointFuns.insert(IRDB->getFunctionDefinition(EntryPoint)); } - // Set initial seeds at the required entry points and generate global + // std::set initial seeds at the required entry points and generate global // integer-typed variables using generalized initial seeds for (const auto *EntryPointFun : EntryPointFuns) { Seeds.addSeed(&EntryPointFun->front().front(), getZeroValue(), @@ -321,32 +293,27 @@ IDELinearConstantAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDELinearConstantAnalysis::isZeroValue( - IDELinearConstantAnalysis::d_t Fact) const { - return LLVMZeroValue::getInstance()->isLLVMZeroValue(Fact); +bool IDELinearConstantAnalysis::isZeroValue(d_t Fact) const { + return LLVMZeroValue::isLLVMZeroValue(Fact); } // In addition provide specifications for the IDE parts -shared_ptr> -IDELinearConstantAnalysis::getNormalEdgeFunction( - IDELinearConstantAnalysis::n_t Curr, - IDELinearConstantAnalysis::d_t CurrNode, - IDELinearConstantAnalysis::n_t /*Succ*/, - IDELinearConstantAnalysis::d_t SuccNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getNormalEdgeFunction(n_t Curr, d_t CurrNode, + n_t /*Succ*/, d_t SuccNode) { // ALL_BOTTOM for zero value if ((isZeroValue(CurrNode) && isZeroValue(SuccNode)) || (llvm::isa(Curr) && isZeroValue(CurrNode))) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Zero value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } // Check store instruction if (const auto *Store = llvm::dyn_cast(Curr)) { - IDELinearConstantAnalysis::d_t PointerOperand = Store->getPointerOperand(); - IDELinearConstantAnalysis::d_t ValueOperand = Store->getValueOperand(); + d_t PointerOperand = Store->getPointerOperand(); + d_t ValueOperand = Store->getValueOperand(); if (PointerOperand == SuccNode) { // Case I: Storing a constant integer. if (isZeroValue(CurrNode) && llvm::isa(ValueOperand)) { @@ -355,14 +322,14 @@ IDELinearConstantAnalysis::getNormalEdgeFunction( LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); const auto *CI = llvm::dyn_cast(ValueOperand); auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } // Case II: Storing an integer typed value. if (CurrNode != SuccNode && ValueOperand->getType()->isIntegerTy()) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Storing an integer typed value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared(); + return std::make_shared(); } } } @@ -373,38 +340,36 @@ IDELinearConstantAnalysis::getNormalEdgeFunction( LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Loading an integer typed value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared(); + return std::make_shared(); } } // Check for binary operations add, sub, mul, udiv/sdiv and urem/srem - if (Curr == SuccNode && llvm::isa(Curr)) { + if (Curr == SuccNode && CurrNode != SuccNode && + llvm::isa(Curr)) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Binary operation."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); unsigned OP = Curr->getOpcode(); auto *Lop = Curr->getOperand(0); auto *Rop = Curr->getOperand(1); // For non linear constant computation we propagate bottom - if (CurrNode == ZeroValue && !llvm::isa(Lop) && - !llvm::isa(Rop)) { - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + if ((CurrNode == Lop && !llvm::isa(Rop)) || + (CurrNode == Rop && !llvm::isa(Lop))) { + return std::make_shared>(BOTTOM); } - return make_shared(OP, Lop, Rop, - CurrNode); + + return std::make_shared(OP, Lop, Rop, CurrNode); } LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Edge identity."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return EdgeIdentity::getInstance(); + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getCallEdgeFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::d_t SrcNode, - IDELinearConstantAnalysis::f_t /*DestinationFunction*/, - IDELinearConstantAnalysis::d_t DestNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getCallEdgeFunction(n_t CallSite, d_t SrcNode, + f_t /*DestinationFunction*/, + d_t DestNode) { // Case: Passing constant integer as parameter if (isZeroValue(SrcNode) && !isZeroValue(DestNode)) { if (const auto *A = llvm::dyn_cast(DestNode)) { @@ -412,49 +377,44 @@ IDELinearConstantAnalysis::getCallEdgeFunction( const auto *Actual = CS->getArgOperand(getFunctionArgumentNr(A)); if (const auto *CI = llvm::dyn_cast(Actual)) { auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } } } return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getReturnEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::f_t /*CalleeFunction*/, - IDELinearConstantAnalysis::n_t ExitStmt, - IDELinearConstantAnalysis::d_t ExitNode, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t RetNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getReturnEdgeFunction(n_t /*CallSite*/, + f_t /*CalleeFunction*/, + n_t ExitStmt, d_t ExitNode, + n_t /*RetSite*/, d_t RetNode) { // Case: Returning constant integer if (isZeroValue(ExitNode) && !isZeroValue(RetNode)) { const auto *Return = llvm::cast(ExitStmt); auto *ReturnValue = Return->getReturnValue(); if (auto *CI = llvm::dyn_cast_or_null(ReturnValue)) { auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } } - return EdgeIdentity::getInstance(); + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getCallToRetEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::d_t /*CallNode*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t /*RetSiteNode*/, - set /*Callees*/) { - return EdgeIdentity::getInstance(); +std::shared_ptr> +IDELinearConstantAnalysis::getCallToRetEdgeFunction(n_t /*CallSite*/, + d_t /*CallNode*/, + n_t /*RetSite*/, + d_t /*RetSiteNode*/, + std::set /*Callees*/) { + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getSummaryEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::d_t /*CallNode*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t /*RetSiteNode*/) { +std::shared_ptr> +IDELinearConstantAnalysis::getSummaryEdgeFunction(n_t /*CallSite*/, + d_t /*CallNode*/, + n_t /*RetSite*/, + d_t /*RetSiteNode*/) { return nullptr; } @@ -466,9 +426,8 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::bottomElement() { return BOTTOM; } -IDELinearConstantAnalysis::l_t -IDELinearConstantAnalysis::join(IDELinearConstantAnalysis::l_t Lhs, - IDELinearConstantAnalysis::l_t Rhs) { +IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::join(l_t Lhs, + l_t Rhs) { if ((Rhs == Lhs) || (Lhs == TOP && Rhs != BOTTOM)) { return Rhs; } @@ -478,20 +437,18 @@ IDELinearConstantAnalysis::join(IDELinearConstantAnalysis::l_t Lhs, return BOTTOM; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::allTopFunction() { - return make_shared>(TOP); + return std::make_shared>(TOP); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAEdgeFunctionComposer::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (auto *AB = dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (auto *EI = dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } if (auto *LCAID = dynamic_cast(SecondFunction.get())) { @@ -500,25 +457,22 @@ IDELinearConstantAnalysis::LCAEdgeFunctionComposer::composeWith( return F->composeWith(G->composeWith(SecondFunction)); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAEdgeFunctionComposer::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (auto *AT = dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } IDELinearConstantAnalysis::GenConstant::GenConstant( IDELinearConstantAnalysis::l_t IntConst) - : GenConstantId(++IDELinearConstantAnalysis::CurrGenConstantId), - IntConst(IntConst) {} + : GenConstantId(++CurrGenConstantId), IntConst(IntConst) {} IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::GenConstant::computeTarget( @@ -526,102 +480,101 @@ IDELinearConstantAnalysis::GenConstant::computeTarget( return IntConst; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::GenConstant::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LSVI = dynamic_cast(SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } - return make_shared( - this->shared_from_this(), SecondFunction); + + auto Res = SecondFunction->computeTarget(IntConst); + + if (Res == TOP) { + return std::make_shared>(TOP); + } + if (Res == BOTTOM) { + return std::make_shared>(BOTTOM); + } + + return std::make_shared(Res); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::GenConstant::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::GenConstant::equal_to( - shared_ptr> Other) const { - if (auto *GC = - dynamic_cast(Other.get())) { + std::shared_ptr> Other) const { + if (auto *GC = dynamic_cast(Other.get())) { return (GC->IntConst == this->IntConst); } return this == Other.get(); } -void IDELinearConstantAnalysis::GenConstant::print(ostream &OS, +void IDELinearConstantAnalysis::GenConstant::print(std::ostream &OS, bool /*IsForDebug*/) const { OS << IntConst << " (EF:" << GenConstantId << ')'; } IDELinearConstantAnalysis::LCAIdentity::LCAIdentity() - : LCAIDId(++IDELinearConstantAnalysis::CurrLCAIDId) {} + : LCAIDId(++CurrLCAIDId) {} IDELinearConstantAnalysis::l_t -IDELinearConstantAnalysis::LCAIdentity::computeTarget( - IDELinearConstantAnalysis::l_t Source) { +IDELinearConstantAnalysis::LCAIdentity::computeTarget(l_t Source) { return Source; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAIdentity::composeWith( - shared_ptr> SecondFunction) { + std::shared_ptr> SecondFunction) { return SecondFunction; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAIdentity::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::LCAIdentity::equal_to( - shared_ptr> Other) const { + std::shared_ptr> Other) const { return this == Other.get(); } -void IDELinearConstantAnalysis::LCAIdentity::print(ostream &OS, +void IDELinearConstantAnalysis::LCAIdentity::print(std::ostream &OS, bool /*IsForDebug*/) const { OS << "Id (EF:" << LCAIDId << ')'; } -IDELinearConstantAnalysis::BinOp::BinOp(const unsigned Op, - IDELinearConstantAnalysis::d_t Lop, - IDELinearConstantAnalysis::d_t Rop, - IDELinearConstantAnalysis::d_t CurrNode) - : EdgeFunctionID(++IDELinearConstantAnalysis::CurrBinaryId), Op(Op), - Lop(Lop), Rop(Rop), CurrNode(CurrNode) {} +IDELinearConstantAnalysis::BinOp::BinOp(const unsigned Op, d_t Lop, d_t Rop, + d_t CurrNode) + : EdgeFunctionID(++CurrBinaryId), Op(Op), Lop(Lop), Rop(Rop), + CurrNode(CurrNode) {} -IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BinOp::computeTarget( - IDELinearConstantAnalysis::l_t Source) { +IDELinearConstantAnalysis::l_t +IDELinearConstantAnalysis::BinOp::computeTarget(l_t Source) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Left Op : " << llvmIRToString(Lop)); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) @@ -630,74 +583,72 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BinOp::computeTarget( << "Curr Node : " << llvmIRToString(CurrNode)); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(CurrNode) && + llvm::errs() << "BinOp::computeTarget(" << Source << ") with Op: " << Op + << ", Lop: " << llvmIRToShortString(Lop) + << ", Rop: " << llvmIRToShortString(Rop) + << ", at CurrNode: " << llvmIRToString(CurrNode) << '\n'; + + if (LLVMZeroValue::isLLVMZeroValue(CurrNode) && llvm::isa(Lop) && llvm::isa(Rop)) { - const auto *Lic = llvm::dyn_cast(Lop); - const auto *Ric = llvm::dyn_cast(Rop); - return IDELinearConstantAnalysis::executeBinOperation( - Op, Lic->getSExtValue(), Ric->getSExtValue()); + const auto *Lic = llvm::cast(Lop); + const auto *Ric = llvm::cast(Rop); + return executeBinOperation(Op, Lic->getSExtValue(), Ric->getSExtValue()); } if (Source == BOTTOM) { return BOTTOM; } if (Lop == CurrNode && llvm::isa(Rop)) { - const auto *Ric = llvm::dyn_cast(Rop); - return IDELinearConstantAnalysis::executeBinOperation(Op, Source, - Ric->getSExtValue()); + const auto *Ric = llvm::cast(Rop); + return executeBinOperation(Op, Source, Ric->getSExtValue()); } if (Rop == CurrNode && llvm::isa(Lop)) { - const auto *Lic = llvm::dyn_cast(Lop); - return IDELinearConstantAnalysis::executeBinOperation( - Op, Lic->getSExtValue(), Source); + const auto *Lic = llvm::cast(Lop); + return executeBinOperation(Op, Lic->getSExtValue(), Source); } - throw runtime_error("Only linear constant propagation can be specified!"); + + throw std::runtime_error( + "Only linear constant propagation can be specified!"); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::BinOp::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LSVI = dynamic_cast( - SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } - return make_shared( - this->shared_from_this(), SecondFunction); + return std::make_shared(this->shared_from_this(), + SecondFunction); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::BinOp::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(IDELinearConstantAnalysis::BOTTOM); } bool IDELinearConstantAnalysis::BinOp::equal_to( - shared_ptr> Other) const { - if (auto *BOP = - dynamic_cast(Other.get())) { + std::shared_ptr> Other) const { + if (auto *BOP = dynamic_cast(Other.get())) { return BOP->Op == this->Op && BOP->Lop == this->Lop && BOP->Rop == this->Rop; } return this == Other.get(); } -void IDELinearConstantAnalysis::BinOp::print(ostream &OS, +void IDELinearConstantAnalysis::BinOp::print(std::ostream &OS, bool /*IsForDebug*/) const { if (const auto *LIC = llvm::dyn_cast(Lop)) { OS << LIC->getSExtValue(); @@ -741,44 +692,50 @@ char IDELinearConstantAnalysis::opToChar(const unsigned Op) { bool IDELinearConstantAnalysis::isEntryPoint( const std::string &FunctionName) const { - return std::find(EntryPoints.begin(), EntryPoints.end(), FunctionName) != - EntryPoints.end(); + return EntryPoints.count(FunctionName); } -IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::executeBinOperation( - const unsigned Op, IDELinearConstantAnalysis::l_t Lop, - IDELinearConstantAnalysis::l_t Rop) { +IDELinearConstantAnalysis::l_t +IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t Lop, + l_t Rop) { + + if (Lop == BOTTOM || Rop == BOTTOM) { + return BOTTOM; + } // default initialize with BOTTOM (all information) - IDELinearConstantAnalysis::l_t Res = BOTTOM; + l_t Res = BOTTOM; switch (Op) { case llvm::Instruction::Add: if (llvm::AddOverflow(Lop, Rop, Res)) { - Res = TOP; + Res = BOTTOM; } break; case llvm::Instruction::Sub: if (llvm::SubOverflow(Lop, Rop, Res)) { - Res = TOP; + Res = BOTTOM; } break; case llvm::Instruction::Mul: if (llvm::MulOverflow(Lop, Rop, Res)) { - Res = TOP; + Res = BOTTOM; } break; case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: - if (Lop == std::numeric_limits::min() && - Rop == -1) { // Would produce and overflow, as the complement of min is - // not representable in a signed type. - return TOP; - } + /// MIN is TOP, so already handled + + // if (Lop == std::numeric_limits::min() && + // Rop == -1) { // Would produce and overflow, as the complement of min + // is + // // not representable in a signed type. + // return BOTTOM; + // } if (Rop == 0) { // Division by zero is UB, so we return TOP - return TOP; + return BOTTOM; } Res = Lop / Rop; break; @@ -786,7 +743,7 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::executeBinOperation( case llvm::Instruction::URem: case llvm::Instruction::SRem: if (Rop == 0) { // Division by zero is UB, so we return TOP - return TOP; + return BOTTOM; } Res = Lop % Rop; break; @@ -801,37 +758,32 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::executeBinOperation( return Res; } -void IDELinearConstantAnalysis::printNode( - ostream &OS, IDELinearConstantAnalysis::n_t Stmt) const { +void IDELinearConstantAnalysis::printNode(std::ostream &OS, n_t Stmt) const { OS << llvmIRToString(Stmt); } -void IDELinearConstantAnalysis::printDataFlowFact( - ostream &OS, IDELinearConstantAnalysis::d_t Fact) const { +void IDELinearConstantAnalysis::printDataFlowFact(std::ostream &OS, + d_t Fact) const { OS << llvmIRToShortString(Fact); } -void IDELinearConstantAnalysis::printFunction( - ostream &OS, IDELinearConstantAnalysis::f_t Func) const { +void IDELinearConstantAnalysis::printFunction(std::ostream &OS, + f_t Func) const { OS << Func->getName().str(); } -void IDELinearConstantAnalysis::printEdgeFact( - ostream &OS, IDELinearConstantAnalysis::l_t L) const { +void IDELinearConstantAnalysis::printEdgeFact(std::ostream &OS, l_t L) const { if (L == BOTTOM) { OS << "Bottom"; } else if (L == TOP) { OS << "Top"; } else { - OS << std::to_string(L); + OS << L; } } void IDELinearConstantAnalysis::emitTextReport( - const SolverResults &SR, - std::ostream &OS) { + const SolverResults &SR, std::ostream &OS) { OS << "\n====================== IDE-Linear-Constant-Analysis Report " "======================\n"; if (!IRDB->debugInfoAvailable()) { @@ -848,7 +800,7 @@ void IDELinearConstantAnalysis::emitTextReport( if (!Results.empty()) { OS << "At IR statement: " << NtoString(Stmt) << '\n'; for (auto Res : Results) { - if (Res.second != IDELinearConstantAnalysis::BOTTOM) { + if (Res.second != BOTTOM) { OS << " Fact: " << DtoString(Res.first) << "\n Value: " << LtoString(Res.second) << '\n'; } @@ -873,10 +825,9 @@ void IDELinearConstantAnalysis::emitTextReport( } void IDELinearConstantAnalysis::stripBottomResults( - std::unordered_map &Res) { + std::unordered_map &Res) { for (auto It = Res.begin(); It != Res.end();) { - if (It->second == IDELinearConstantAnalysis::BOTTOM) { + if (It->second == BOTTOM) { It = Res.erase(It); } else { ++It; @@ -885,11 +836,7 @@ void IDELinearConstantAnalysis::stripBottomResults( } IDELinearConstantAnalysis::lca_results_t -IDELinearConstantAnalysis::getLCAResults( - SolverResults - SR) { +IDELinearConstantAnalysis::getLCAResults(SolverResults SR) { std::map> AggResults; std::cout << "\n==== Computing LCA Results ====\n"; for (const auto *F : ICF->getAllFunctions()) { diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp index 44af1ab3d7..4bbc78d785 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp @@ -256,6 +256,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_05) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 42); GroundTruth.emplace("main", 8, "j", 10); + // The computation j + 32 gives the same value (42) that i had before: + GroundTruth.emplace("main", 8, "i", 42); compareResults(Results, GroundTruth); } @@ -277,6 +279,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_07) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 30); GroundTruth.emplace("main", 8, "j", 10); + // The computation j + 20 gives the same value (30) that i had before: + GroundTruth.emplace("main", 8, "i", 30); compareResults(Results, GroundTruth); } @@ -750,7 +754,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleAddOverflow) { auto Results = doAnalysis("overflow_add_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", 9223372036854775806); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -758,7 +762,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleSubOverflow) { auto Results = doAnalysis("overflow_sub_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", -9223372036854775807); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -766,7 +770,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleMulOverflow) { auto Results = doAnalysis("overflow_mul_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", 9223372036854775806); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -774,8 +778,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleDivOverflowForMinIntDivByOne) { auto Results = doAnalysis("overflow_div_min_by_neg_one_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", -9223372036854775807); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); - GroundTruth.emplace("main", 6, "k", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "k", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -785,7 +789,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleDivisionByZero) { auto Results = doAnalysis("ub_division_by_zero_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 4, "i", 42); - GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -793,7 +797,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleModuloByZero) { auto Results = doAnalysis("ub_modulo_by_zero_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 4, "i", 42); - GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp index f882fd3b30..113c260ae2 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp @@ -251,6 +251,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_05) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 42); GroundTruth.emplace("main", 8, "j", 10); + GroundTruth.emplace("main", 8, "i", 42); compareResults(Results, GroundTruth); } @@ -272,6 +273,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_07) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 30); GroundTruth.emplace("main", 8, "j", 10); + GroundTruth.emplace("main", 8, "i", 30); compareResults(Results, GroundTruth); } From f44634ae38ba862f714de409536ffc8de9856157 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 5 Jan 2022 11:44:08 +0100 Subject: [PATCH 2/7] minor --- .../Problems/IDELinearConstantAnalysis.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 03926c2899..dbc4c13268 100644 --- a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -428,10 +428,10 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::bottomElement() { IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::join(l_t Lhs, l_t Rhs) { - if ((Rhs == Lhs) || (Lhs == TOP && Rhs != BOTTOM)) { + if (Rhs == Lhs || Lhs == TOP) { return Rhs; } - if (Rhs == TOP && Lhs != BOTTOM) { + if (Rhs == TOP) { return Lhs; } return BOTTOM; @@ -445,13 +445,13 @@ IDELinearConstantAnalysis::allTopFunction() { std::shared_ptr> IDELinearConstantAnalysis::LCAEdgeFunctionComposer::composeWith( std::shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>(SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>(SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LCAID = dynamic_cast(SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } return F->composeWith(G->composeWith(SecondFunction)); @@ -464,7 +464,7 @@ IDELinearConstantAnalysis::LCAEdgeFunctionComposer::joinWith( OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>(OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } return std::make_shared>(BOTTOM); @@ -622,6 +622,9 @@ IDELinearConstantAnalysis::BinOp::composeWith( if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } + if (dynamic_cast(SecondFunction.get())) { + return SecondFunction; + } return std::make_shared(this->shared_from_this(), SecondFunction); } @@ -636,7 +639,7 @@ IDELinearConstantAnalysis::BinOp::joinWith( if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return std::make_shared>(IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::BinOp::equal_to( From e670cc2e1f250a4879596ed93f200654206fb63d Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 5 Jan 2022 13:16:40 +0100 Subject: [PATCH 3/7] Use LatticeDomain instead of int64_t in IDE-LCA --- .../Problems/IDELinearConstantAnalysis.h | 9 +- .../phasar/PhasarLLVM/Utils/LatticeDomain.h | 43 ++++--- .../Problems/IDELinearConstantAnalysis.cpp | 109 ++++++++---------- .../IDELinearConstantAnalysisTest.cpp | 4 +- .../IDELinearConstantAnalysis_DotTest.cpp | 4 +- 5 files changed, 85 insertions(+), 84 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h index 81f7bd7655..e73bfceca0 100644 --- a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -19,6 +19,7 @@ #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/EdgeFunctionComposer.h" #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/IDETabulationProblem.h" #include "phasar/PhasarLLVM/Domain/AnalysisDomain.h" +#include "phasar/PhasarLLVM/Utils/LatticeDomain.h" namespace llvm { class Instruction; @@ -31,7 +32,7 @@ namespace psr { struct IDELinearConstantAnalysisDomain : public LLVMAnalysisDomainDefault { // int64_t corresponds to llvm's type of constant integer - using l_t = int64_t; + using l_t = LatticeDomain; }; class LLVMBasedICFG; @@ -176,10 +177,10 @@ class IDELinearConstantAnalysis public std::enable_shared_from_this { private: const unsigned GenConstantId; - const l_t IntConst; + const int64_t IntConst; public: - explicit GenConstant(l_t IntConst); + explicit GenConstant(int64_t IntConst); l_t computeTarget(l_t Source) override; @@ -253,7 +254,7 @@ class IDELinearConstantAnalysis * @param rop right operand * @return Result of binary operation */ - static l_t executeBinOperation(unsigned Op, l_t Lop, l_t Rop); + static l_t executeBinOperation(unsigned Op, l_t LVal, l_t RVal); static char opToChar(unsigned Op); diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index 7606507fc2..c066993bca 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -13,6 +13,7 @@ #include "llvm/Support/ErrorHandling.h" #include +#include #include namespace psr { @@ -22,8 +23,7 @@ namespace psr { /// the lattice. struct Top {}; -static inline std::ostream &operator<<(std::ostream &OS, - [[maybe_unused]] const Top &T) { +static inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) { return OS << "Top"; } @@ -32,8 +32,7 @@ static inline std::ostream &operator<<(std::ostream &OS, /// of the lattice. struct Bottom {}; -static inline std::ostream &operator<<(std::ostream &OS, - [[maybe_unused]] const Bottom &B) { +static inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) { return OS << "Bottom"; } @@ -42,33 +41,43 @@ template using LatticeDomain = std::variant; template inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) { - if (auto T = std::get_if(&LD)) { - return OS << *T; - } - if (auto B = std::get_if(&LD)) { - return OS << *B; - } - return OS << std::get(LD); + std::visit([&OS](const auto &LVal) { OS << LVal; }, LD); + return OS; } template inline bool operator==(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { - if (std::holds_alternative(Lhs) && std::holds_alternative(Rhs)) { - return true; - } - if (std::holds_alternative(Lhs) && - std::holds_alternative(Rhs)) { - return true; + if (Lhs.index() != Rhs.index()) { + return false; } + if (auto LhsPtr = std::get_if(&Lhs)) { if (auto RhsPtr = std::get_if(&Rhs)) { return *LhsPtr == *RhsPtr; } } + + return true; +} + +template < + typename L, typename LL, + typename = std::void_t() == std::declval())>> +inline bool operator==(const LL &Lhs, const LatticeDomain Rhs) { + if (const auto *RVal = std::get_if(&Rhs)) { + return Lhs == *RVal; + } return false; } +template < + typename L, typename LL, + typename = std::void_t() == std::declval())>> +inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { + return Rhs == Lhs; +} + template inline bool operator!=(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { diff --git a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index dbc4c13268..664d69caf2 100644 --- a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -45,11 +45,10 @@ unsigned IDELinearConstantAnalysis::CurrGenConstantId = 0; // NOLINT unsigned IDELinearConstantAnalysis::CurrLCAIDId = 0; // NOLINT unsigned IDELinearConstantAnalysis::CurrBinaryId = 0; // NOLINT -const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = - std::numeric_limits::min(); +const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = Top{}; const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BOTTOM = - std::numeric_limits::max(); + Bottom{}; IDELinearConstantAnalysis::IDELinearConstantAnalysis( const ProjectIRDB *IRDB, const LLVMTypeHierarchy *TH, @@ -470,8 +469,7 @@ IDELinearConstantAnalysis::LCAEdgeFunctionComposer::joinWith( return std::make_shared>(BOTTOM); } -IDELinearConstantAnalysis::GenConstant::GenConstant( - IDELinearConstantAnalysis::l_t IntConst) +IDELinearConstantAnalysis::GenConstant::GenConstant(int64_t IntConst) : GenConstantId(++CurrGenConstantId), IntConst(IntConst) {} IDELinearConstantAnalysis::l_t @@ -502,7 +500,7 @@ IDELinearConstantAnalysis::GenConstant::composeWith( return std::make_shared>(BOTTOM); } - return std::make_shared(Res); + return std::make_shared(std::get(Res)); } std::shared_ptr> @@ -583,11 +581,6 @@ IDELinearConstantAnalysis::BinOp::computeTarget(l_t Source) { << "Curr Node : " << llvmIRToString(CurrNode)); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - llvm::errs() << "BinOp::computeTarget(" << Source << ") with Op: " << Op - << ", Lop: " << llvmIRToShortString(Lop) - << ", Rop: " << llvmIRToShortString(Rop) - << ", at CurrNode: " << llvmIRToString(CurrNode) << '\n'; - if (LLVMZeroValue::isLLVMZeroValue(CurrNode) && llvm::isa(Lop) && llvm::isa(Rop)) { const auto *Lic = llvm::cast(Lop); @@ -667,30 +660,28 @@ void IDELinearConstantAnalysis::BinOp::print(std::ostream &OS, } char IDELinearConstantAnalysis::opToChar(const unsigned Op) { - char OpAsChar; switch (Op) { case llvm::Instruction::Add: - OpAsChar = '+'; - break; + return '+'; case llvm::Instruction::Sub: - OpAsChar = '-'; - break; + return '-'; case llvm::Instruction::Mul: - OpAsChar = '*'; - break; + return '*'; case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: - OpAsChar = '/'; - break; + return '/'; case llvm::Instruction::URem: case llvm::Instruction::SRem: - OpAsChar = '%'; - break; + return '%'; + case llvm::Instruction::And: + return '&'; + case llvm::Instruction::Or: + return '|'; + case llvm::Instruction::Xor: + return '^'; default: - OpAsChar = ' '; - break; + return ' '; } - return OpAsChar; } bool IDELinearConstantAnalysis::isEntryPoint( @@ -699,66 +690,72 @@ bool IDELinearConstantAnalysis::isEntryPoint( } IDELinearConstantAnalysis::l_t -IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t Lop, - l_t Rop) { +IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t LVal, + l_t RVal) { + + auto *LopPtr = std::get_if(&LVal); + auto *RopPtr = std::get_if(&RVal); - if (Lop == BOTTOM || Rop == BOTTOM) { + if (!LopPtr || !RopPtr) { return BOTTOM; } + auto Lop = *LopPtr; + auto Rop = *RopPtr; + // default initialize with BOTTOM (all information) - l_t Res = BOTTOM; + int64_t Res; switch (Op) { case llvm::Instruction::Add: if (llvm::AddOverflow(Lop, Rop, Res)) { - Res = BOTTOM; + return BOTTOM; } - break; + return Res; case llvm::Instruction::Sub: if (llvm::SubOverflow(Lop, Rop, Res)) { - Res = BOTTOM; + return BOTTOM; } - break; + return Res; case llvm::Instruction::Mul: if (llvm::MulOverflow(Lop, Rop, Res)) { - Res = BOTTOM; + return BOTTOM; } - break; + return Res; case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: - /// MIN is TOP, so already handled - - // if (Lop == std::numeric_limits::min() && - // Rop == -1) { // Would produce and overflow, as the complement of min - // is - // // not representable in a signed type. - // return BOTTOM; - // } - if (Rop == 0) { // Division by zero is UB, so we return TOP + if (Lop == std::numeric_limits::min() && + Rop == -1) { // Would produce and overflow, as the complement of min is + // not representable in a signed type. + return TOP; + } + if (Rop == 0) { // Division by zero is UB, so we return Bot return BOTTOM; } - Res = Lop / Rop; - break; + return Lop / Rop; case llvm::Instruction::URem: case llvm::Instruction::SRem: - if (Rop == 0) { // Division by zero is UB, so we return TOP + if (Rop == 0) { // Division by zero is UB, so we return Bot return BOTTOM; } - Res = Lop % Rop; - break; - + return Lop % Rop; + + case llvm::Instruction::And: + return Lop & Rop; + case llvm::Instruction::Or: + return Lop | Rop; + case llvm::Instruction::Xor: + return Lop ^ Rop; default: LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Operation not supported by " "IDELinearConstantAnalysis::" "executeBinOperation()"); - break; + return BOTTOM; } - return Res; } void IDELinearConstantAnalysis::printNode(std::ostream &OS, n_t Stmt) const { @@ -776,13 +773,7 @@ void IDELinearConstantAnalysis::printFunction(std::ostream &OS, } void IDELinearConstantAnalysis::printEdgeFact(std::ostream &OS, l_t L) const { - if (L == BOTTOM) { - OS << "Bottom"; - } else if (L == TOP) { - OS << "Top"; - } else { - OS << L; - } + OS << L; } void IDELinearConstantAnalysis::emitTextReport( diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp index 4bbc78d785..81868542e8 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp @@ -23,8 +23,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { unittest::PathToLLTestFiles + "linear_constant/"; // Function - Line Nr - Variable - Value - using LCACompactResult_t = - std::tuple; + using LCACompactResult_t = std::tuple; std::unique_ptr IRDB; void SetUp() override { boost::log::core::get()->set_logging_enabled(false); } diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp index 113c260ae2..31dde3d372 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp @@ -24,8 +24,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { const std::set EntryPoints = {"main"}; // Function - Line Nr - Variable - Value - using LCACompactResult_t = - std::tuple; + using LCACompactResult_t = std::tuple; std::unique_ptr IRDB; void SetUp() override { boost::log::core::get()->set_logging_enabled(false); } From f9f1a3ac775f15a4cf610eaf475ca5596dff4853 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 5 Jan 2022 14:23:40 +0100 Subject: [PATCH 4/7] Made LatticeDomain an own class, such that free functions don't get confused with std::variant --- .../phasar/PhasarLLVM/Utils/LatticeDomain.h | 95 +++++++++++++++---- 1 file changed, 75 insertions(+), 20 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index c066993bca..c8d25f3248 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include #include @@ -23,7 +24,11 @@ namespace psr { /// the lattice. struct Top {}; -static inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) { +inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) { + return OS << "Top"; +} + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Top /*unused*/) { return OS << "Top"; } @@ -32,17 +37,66 @@ static inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) { /// of the lattice. struct Bottom {}; -static inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) { +inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) { return OS << "Bottom"; } -/// A easy shorthand to construct a complete lattice of L. -template using LatticeDomain = std::variant; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Bottom /*unused*/) { + return OS << "Bottom"; +} +/// A easy shorthand to construct a complete lattice of L. template +struct LatticeDomain : public std::variant { + using std::variant::variant; + + [[nodiscard]] inline bool isBottom() const noexcept { + return std::holds_alternative(*this); + } + [[nodiscard]] inline bool isTop() const noexcept { + return std::holds_alternative(*this); + } + [[nodiscard]] inline L *getValueOrNull() noexcept { + return std::get_if(this); + } + [[nodiscard]] inline const L *getValueOrNull() const noexcept { + return std::get_if(this); + } +}; + +// template using LatticeDomain = std::variant; + +template () + << std::declval())>> inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) { - std::visit([&OS](const auto &LVal) { OS << LVal; }, LD); - return OS; + if (LD.isBottom()) { + return OS << "Bottom"; + } + if (LD.isTop()) { + return OS << "Top"; + } + + const auto *Val = LD.getValueOrNull(); + assert(Val && "Only alternative remaining is L"); + return OS << *Val; +} + +template () + << std::declval())>> +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const LatticeDomain &LD) { + if (LD.isBottom()) { + return OS << "Bottom"; + } + if (LD.isTop()) { + return OS << "Top"; + } + + const auto *Val = LD.getValueOrNull(); + assert(Val && "Only alternative remaining is L"); + return OS << *Val; } template @@ -52,10 +106,9 @@ inline bool operator==(const LatticeDomain &Lhs, return false; } - if (auto LhsPtr = std::get_if(&Lhs)) { - if (auto RhsPtr = std::get_if(&Rhs)) { - return *LhsPtr == *RhsPtr; - } + if (auto LhsPtr = Lhs.getValueOrNull()) { + /// No need to check whether Lhs is an L; the indices are already the same + return *LhsPtr == *Rhs.getValueOrNull(); } return true; @@ -65,7 +118,7 @@ template < typename L, typename LL, typename = std::void_t() == std::declval())>> inline bool operator==(const LL &Lhs, const LatticeDomain Rhs) { - if (const auto *RVal = std::get_if(&Rhs)) { + if (const auto *RVal = Rhs.getValueOrNull()) { return Lhs == *RVal; } return false; @@ -87,26 +140,28 @@ inline bool operator!=(const LatticeDomain &Lhs, template inline bool operator<(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { - // Top < (Lhs::L < Rhs::L) < Bottom - if (std::holds_alternative(Rhs)) { + /// Top < (Lhs::L < Rhs::L) < Bottom + if (Rhs.isTop()) { return false; } - if (std::holds_alternative(Lhs)) { + if (Lhs.isTop()) { return true; } - if (auto LhsPtr = std::get_if(&Lhs)) { - if (auto RhsPtr = std::get_if(&Rhs)) { + if (auto LhsPtr = Lhs.getValueOrNull()) { + if (auto RhsPtr = Rhs.getValueOrNull()) { return *LhsPtr < *RhsPtr; } } - if (std::holds_alternative(Rhs)) { - return !std::holds_alternative(Lhs); - } - if (std::holds_alternative(Lhs)) { + if (Lhs.isBottom()) { return false; } + + if (Rhs.isBottom()) { + return true; + } + llvm_unreachable("All comparision cases should be handled above."); } From e5c5c690982fdbec9ca1b0babba0b970c1cfd5f8 Mon Sep 17 00:00:00 2001 From: Philipp Schubert Date: Wed, 12 Jan 2022 09:02:01 +0100 Subject: [PATCH 5/7] allow further comparison operator for LatticeDomain --- .../phasar/PhasarLLVM/Utils/LatticeDomain.h | 19 ++++++++++++++++--- include/phasar/Utils/TypeTraits.h | 10 ++++++++++ .../Mono/Problems/InterMonoSolverTest.cpp | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index 4db15bba45..86e5b1fbb8 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -10,13 +10,15 @@ #ifndef PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H #define PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" - #include #include #include +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#include "phasar/Utils/TypeTraits.h" + namespace psr { /// Represents the infimum of the lattice: @@ -119,6 +121,17 @@ inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { return Rhs == Lhs; } +template +inline bool operator==(const L &Lhs, const M &Rhs) { + if constexpr (is_variant_v) { + return Lhs == std::variant(Rhs); + } + if constexpr (is_variant_v) { + return std::variant(Lhs) == Rhs; + } + return Lhs == Rhs; +} + template inline bool operator!=(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index 1cf2754848..5bacd954a6 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "llvm/Support/raw_ostream.h" @@ -109,6 +110,15 @@ constexpr bool is_std_hashable_v = detail::is_std_hashable::value; // NOLINT template constexpr bool is_llvm_hashable_v = // NOLINT detail::is_llvm_hashable::value; + +template struct is_variant : std::false_type {}; // NOLINT + +template +struct is_variant> : std::true_type {}; // NOLINT + +template +inline constexpr bool is_variant_v = is_variant::value; // NOLINT + // NOLINTEND(readability-identifier-naming) } // namespace psr diff --git a/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp b/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp index 2c72c07a24..f13f4b48c7 100644 --- a/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp @@ -67,7 +67,7 @@ InterMonoSolverTest::callFlow(InterMonoSolverTest::n_t CallSite, const InterMonoSolverTest::mono_container_t &In) { cout << "InterMonoSolverTest::callFlow()\n"; InterMonoSolverTest::mono_container_t Result; - Result.setUnion(In); + Result = Result.setUnion(In); if (const auto *const Call = llvm::dyn_cast(CallSite)) { Result.insert(Call); } From 5d08e5044b80e89399471d2a18a036f124ecc8c1 Mon Sep 17 00:00:00 2001 From: Philipp Schubert Date: Wed, 12 Jan 2022 09:18:46 +0100 Subject: [PATCH 6/7] not quite --- include/phasar/PhasarLLVM/Utils/LatticeDomain.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index 86e5b1fbb8..38bcc2eb82 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -66,8 +66,6 @@ struct LatticeDomain : public std::variant { } }; -// template using LatticeDomain = std::variant; - template () << std::declval())>> @@ -123,10 +121,10 @@ inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { template inline bool operator==(const L &Lhs, const M &Rhs) { - if constexpr (is_variant_v) { + if constexpr (is_variant_v && !is_variant_v) { return Lhs == std::variant(Rhs); } - if constexpr (is_variant_v) { + if constexpr (!is_variant_v && is_variant_v) { return std::variant(Lhs) == Rhs; } return Lhs == Rhs; From 23c0d215dbffe448dd326b7cf395a6a15ec5d96c Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 12 Jan 2022 09:40:28 +0100 Subject: [PATCH 7/7] Fix merge error --- .../phasar/PhasarLLVM/Utils/LatticeDomain.h | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index 38bcc2eb82..3df8a6c26f 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -115,19 +115,18 @@ inline bool operator==(const LatticeDomain &Lhs, template < typename L, typename LL, typename = std::void_t() == std::declval())>> -inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { - return Rhs == Lhs; +inline bool operator==(const LL &Lhs, const LatticeDomain Rhs) { + if (auto RVal = Rhs.getValueOrNull()) { + return Lhs == *RVal; + } + return false; } -template -inline bool operator==(const L &Lhs, const M &Rhs) { - if constexpr (is_variant_v && !is_variant_v) { - return Lhs == std::variant(Rhs); - } - if constexpr (!is_variant_v && is_variant_v) { - return std::variant(Lhs) == Rhs; - } - return Lhs == Rhs; +template < + typename L, typename LL, + typename = std::void_t() == std::declval())>> +inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { + return Rhs == Lhs; } template