From 263ef58cff935158d8ea2d35e6f0effd5693c924 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:25:41 +0200 Subject: [PATCH] Small refactoring of LLVMBasedAliasAnalysis + allow disabling the CFL-based alias analyses (#626) --- .../ControlFlow/CallGraphAnalysisType.def | 2 +- .../Pointer/LLVMBasedAliasAnalysis.h | 45 +++++++----- .../PhasarLLVM/Utils/BasicBlockOrdering.h | 1 + include/phasar/Pointer/AliasAnalysisType.def | 3 +- lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp | 3 +- .../Pointer/LLVMBasedAliasAnalysis.cpp | 69 ++++++++++++------- lib/PhasarLLVM/Utils/BasicBlockOrdering.cpp | 1 - 7 files changed, 77 insertions(+), 47 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraphAnalysisType.def b/include/phasar/ControlFlow/CallGraphAnalysisType.def index c136232c0..3430b21c0 100644 --- a/include/phasar/ControlFlow/CallGraphAnalysisType.def +++ b/include/phasar/ControlFlow/CallGraphAnalysisType.def @@ -16,6 +16,6 @@ CALL_GRAPH_ANALYSIS_TYPE(CHA, "cha", "Class hierarchy analysis") CALL_GRAPH_ANALYSIS_TYPE(RTA, "rta", "Rapid type analysis") CALL_GRAPH_ANALYSIS_TYPE(DTA, "dta", "Declared type analysis") CALL_GRAPH_ANALYSIS_TYPE(VTA, "vta", "Variable type analysis") -CALL_GRAPH_ANALYSIS_TYPE(OTF, "otf", "On-the-fly analysis based on points-to info") +CALL_GRAPH_ANALYSIS_TYPE(OTF, "otf", "On-the-fly analysis based on points-to info (default)") #undef CALL_GRAPH_ANALYSIS_TYPE diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h b/include/phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h index e724a0c4d..c37cfda21 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h @@ -13,8 +13,6 @@ #include "phasar/Pointer/AliasAnalysisType.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/IR/PassManager.h" -#include "llvm/Passes/PassBuilder.h" namespace llvm { class Value; @@ -27,23 +25,19 @@ namespace psr { class LLVMProjectIRDB; class LLVMBasedAliasAnalysis { -private: - llvm::PassBuilder PB; - llvm::AAManager AA; - llvm::FunctionAnalysisManager FAM; - llvm::FunctionPassManager FPM; - llvm::DenseMap AAInfos; - AliasAnalysisType PATy; - - [[nodiscard]] bool hasAliasInfo(const llvm::Function &Fun) const; - - void computeAliasInfo(llvm::Function &Fun); public: - LLVMBasedAliasAnalysis(LLVMProjectIRDB &IRDB, bool UseLazyEvaluation = true, - AliasAnalysisType PATy = AliasAnalysisType::CFLAnders); + explicit LLVMBasedAliasAnalysis( + LLVMProjectIRDB &IRDB, bool UseLazyEvaluation, + AliasAnalysisType PATy = AliasAnalysisType::Basic); - ~LLVMBasedAliasAnalysis() = default; + LLVMBasedAliasAnalysis(LLVMBasedAliasAnalysis &&) noexcept = default; + LLVMBasedAliasAnalysis & + operator=(LLVMBasedAliasAnalysis &&) noexcept = default; + + LLVMBasedAliasAnalysis(const LLVMBasedAliasAnalysis &) = delete; + LLVMBasedAliasAnalysis &operator=(const LLVMBasedAliasAnalysis &) = delete; + ~LLVMBasedAliasAnalysis(); void print(llvm::raw_ostream &OS = llvm::outs()) const; @@ -54,13 +48,26 @@ class LLVMBasedAliasAnalysis { return AAInfos.lookup(F); }; - void erase(llvm::Function *F); + void erase(llvm::Function *F) noexcept; - void clear(); + void clear() noexcept; - [[nodiscard]] inline AliasAnalysisType getPointerAnalysisType() const { + [[nodiscard]] inline AliasAnalysisType + getPointerAnalysisType() const noexcept { return PATy; }; + +private: + [[nodiscard]] bool hasAliasInfo(const llvm::Function &Fun) const; + + void computeAliasInfo(llvm::Function &Fun); + + // -- data members + + struct Impl; + std::unique_ptr PImpl; + AliasAnalysisType PATy; + llvm::DenseMap AAInfos; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Utils/BasicBlockOrdering.h b/include/phasar/PhasarLLVM/Utils/BasicBlockOrdering.h index 664f28304..4ec3570b5 100644 --- a/include/phasar/PhasarLLVM/Utils/BasicBlockOrdering.h +++ b/include/phasar/PhasarLLVM/Utils/BasicBlockOrdering.h @@ -12,6 +12,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FunctionExtras.h" +#include "llvm/IR/Dominators.h" #include #include diff --git a/include/phasar/Pointer/AliasAnalysisType.def b/include/phasar/Pointer/AliasAnalysisType.def index 23fbe08c7..93c3599d7 100644 --- a/include/phasar/Pointer/AliasAnalysisType.def +++ b/include/phasar/Pointer/AliasAnalysisType.def @@ -11,8 +11,9 @@ #define ALIAS_ANALYSIS_TYPE(NAME, CMDFLAG, DESC) #endif +ALIAS_ANALYSIS_TYPE(Basic, "basic", "Basic LLVM alias resolving based on simple, local properties") ALIAS_ANALYSIS_TYPE(CFLSteens, "cflsteens", "Steensgaard-style alias analysis (equality-based)") -ALIAS_ANALYSIS_TYPE(CFLAnders, "cflanders", "Andersen-style alias analysis (subset-based)") +ALIAS_ANALYSIS_TYPE(CFLAnders, "cflanders", "Andersen-style alias analysis (subset-based) (default)") ALIAS_ANALYSIS_TYPE(PointsTo, "points-to", "Alias-information based on (external) points-to information") #undef ALIAS_ANALYSIS_TYPE diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp index b50121f61..07902f06c 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -13,6 +13,7 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Pointer/AliasAnalysisType.h" #include "phasar/Utils/BoxedPointer.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/NlohmannLogging.h" @@ -96,7 +97,7 @@ LLVMAliasSet::LLVMAliasSet(LLVMProjectIRDB *IRDB, bool UseLazyEvaluation, LLVMAliasSet::LLVMAliasSet(LLVMProjectIRDB *IRDB, const nlohmann::json &SerializedPTS) - : PTA(*IRDB) { + : PTA(*IRDB, true) { assert(IRDB != nullptr); // Assume, we already have validated the json schema diff --git a/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp b/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp index 116fc022c..319dbc4b7 100644 --- a/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.cpp @@ -11,6 +11,7 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Pointer/LLVMPointsToUtils.h" +#include "phasar/Pointer/AliasAnalysisType.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" @@ -19,6 +20,7 @@ #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/CFLAndersAliasAnalysis.h" #include "llvm/Analysis/CFLSteensAliasAnalysis.h" +#include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/Argument.h" #include "llvm/IR/BasicBlock.h" @@ -28,11 +30,18 @@ #include "llvm/IR/PassManager.h" #include "llvm/IR/Value.h" #include "llvm/IR/Verifier.h" +#include "llvm/Passes/PassBuilder.h" using namespace psr; namespace psr { +struct LLVMBasedAliasAnalysis::Impl { + llvm::PassBuilder PB{}; + llvm::FunctionAnalysisManager FAM{}; + llvm::FunctionPassManager FPM{}; +}; + static void printResults(llvm::AliasResult AR, bool P, const llvm::Value *V1, const llvm::Value *V2, const llvm::Module *M) { if (P) { @@ -88,44 +97,54 @@ bool LLVMBasedAliasAnalysis::hasAliasInfo(const llvm::Function &Fun) const { } void LLVMBasedAliasAnalysis::computeAliasInfo(llvm::Function &Fun) { - llvm::PreservedAnalyses PA = FPM.run(Fun, FAM); - llvm::AAResults &AAR = FAM.getResult(Fun); + assert(PImpl != nullptr); + llvm::PreservedAnalyses PA = PImpl->FPM.run(Fun, PImpl->FAM); + llvm::AAResults &AAR = PImpl->FAM.getResult(Fun); AAInfos.insert(std::make_pair(&Fun, &AAR)); } -void LLVMBasedAliasAnalysis::erase(llvm::Function *F) { +void LLVMBasedAliasAnalysis::erase(llvm::Function *F) noexcept { // after we clear all stuff, we need to set it up for the next function-wise // analysis AAInfos.erase(F); - FAM.clear(*F, F->getName()); + PImpl->FAM.clear(*F, F->getName()); } -void LLVMBasedAliasAnalysis::clear() { +void LLVMBasedAliasAnalysis::clear() noexcept { AAInfos.clear(); - FAM.clear(); + PImpl->FAM.clear(); } LLVMBasedAliasAnalysis::LLVMBasedAliasAnalysis(LLVMProjectIRDB &IRDB, bool UseLazyEvaluation, AliasAnalysisType PATy) - : PATy(PATy) { - AA.registerFunctionAnalysis(); - switch (PATy) { - case AliasAnalysisType::CFLAnders: - AA.registerFunctionAnalysis(); - break; - case AliasAnalysisType::CFLSteens: - AA.registerFunctionAnalysis(); - break; - default: - break; - } - AA.registerFunctionAnalysis(); - FAM.registerPass([&] { return std::move(AA); }); - PB.registerFunctionAnalyses(FAM); - llvm::FunctionPassManager FPM; - // Always verify the input. - FPM.addPass(llvm::VerifierPass()); + : PImpl(new Impl{}), PATy(PATy) { + + PImpl->FAM.registerPass([&] { + llvm::AAManager AA; + switch (PATy) { + case AliasAnalysisType::CFLAnders: + AA.registerFunctionAnalysis(); + break; + case AliasAnalysisType::CFLSteens: + AA.registerFunctionAnalysis(); + break; + case AliasAnalysisType::Basic: + [[fallthrough]]; + default: + break; + } + // Note: The order of the alias analyses is important. See LLVM's source + // code for reference (e.g. registerAAAnalyses() in + // llvm/CodeGen/CodeGenPassBuilder.h) + // + AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); + return AA; + }); + PImpl->PB.registerFunctionAnalyses(PImpl->FAM); + if (!UseLazyEvaluation) { for (auto &F : *IRDB.getModule()) { if (!F.isDeclaration()) { @@ -135,6 +154,8 @@ LLVMBasedAliasAnalysis::LLVMBasedAliasAnalysis(LLVMProjectIRDB &IRDB, } } +LLVMBasedAliasAnalysis::~LLVMBasedAliasAnalysis() = default; + void LLVMBasedAliasAnalysis::print(llvm::raw_ostream &OS) const { OS << "Points-to Info:\n"; for (const auto &[Fn, AA] : AAInfos) { diff --git a/lib/PhasarLLVM/Utils/BasicBlockOrdering.cpp b/lib/PhasarLLVM/Utils/BasicBlockOrdering.cpp index 89a5f386a..ee642b6e1 100644 --- a/lib/PhasarLLVM/Utils/BasicBlockOrdering.cpp +++ b/lib/PhasarLLVM/Utils/BasicBlockOrdering.cpp @@ -2,7 +2,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h"