From e6ffc3b23dd258716594e79b8484f097739dd539 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 27 Nov 2023 15:21:59 +0100 Subject: [PATCH 1/8] Add some more statistics --- .../Passes/GeneralStatisticsAnalysis.h | 75 +++++++++++++------ .../Passes/GeneralStatisticsAnalysis.cpp | 62 +++++++++------ 2 files changed, 93 insertions(+), 44 deletions(-) diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index ca6767a3ae..a1d092c36c 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -33,9 +33,8 @@ class Module; namespace psr { -class GeneralStatistics { -private: - friend class GeneralStatisticsAnalysis; +struct GeneralStatistics { + size_t Functions = 0; size_t Globals = 0; size_t BasicBlocks = 0; @@ -50,90 +49,122 @@ class GeneralStatistics { size_t GetElementPtrs = 0; size_t PhiNodes = 0; size_t GlobalConsts = 0; + size_t NumInlineAsm = 0; + size_t IndCalls = 0; std::set AllocatedTypes; std::set AllocaInstructions; std::set RetResInstructions; - std::string ModuleName = ""; + std::string ModuleName{}; -public: /** * @brief Returns the number of Allocation sites. */ - [[nodiscard]] size_t getAllocationsites() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use AllocationSites instead")]] size_t + getAllocationsites() const; /** * @brief Returns the number of Function calls. */ - [[nodiscard]] size_t getFunctioncalls() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use CallSites instead")]] size_t + getFunctioncalls() const; /** * @brief Returns the number of Instructions. */ - [[nodiscard]] size_t getInstructions() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use Instructions instead")]] size_t + getInstructions() const; /** * @brief Returns the number of global pointers. */ - [[nodiscard]] size_t getGlobalPointers() const; + [[nodiscard]] [[deprecated( + "All globals are pointers. Use Globals instead")]] size_t + getGlobalPointers() const; /** * @brief Returns the number of basic blocks. */ - [[nodiscard]] size_t getBasicBlocks() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use BasicBlocks instead")]] size_t + getBasicBlocks() const; /** * @brief Returns the number of functions. */ - [[nodiscard]] size_t getFunctions() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use Functions instead")]] size_t + getFunctions() const; /** * @brief Returns the number of globals. */ - [[nodiscard]] size_t getGlobals() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use Globals instead")]] size_t + getGlobals() const; /** * @brief Returns the number of constant globals. */ - [[nodiscard]] size_t getGlobalConsts() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use GlobalConsts instead")]] size_t + getGlobalConsts() const; /** * @brief Returns the number of memory intrinsics. */ - [[nodiscard]] size_t getMemoryIntrinsics() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use MemIntrinsics instead")]] size_t + getMemoryIntrinsics() const; /** * @brief Returns the number of store instructions. */ - [[nodiscard]] size_t getStoreInstructions() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use StoreInstructions instead")]] size_t + getStoreInstructions() const; /** * @brief Returns the number of load instructions. */ - [[nodiscard]] size_t getLoadInstructions(); + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use LoadInstructions instead; this " + "function seems to be broken anyway")]] size_t + getLoadInstructions(); /** * @brief Returns all possible Types. */ - [[nodiscard]] const std::set &getAllocatedTypes() const; + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use AllocatedTypes instead")]] const std:: + set & + getAllocatedTypes() const; /** * @brief Returns all stack and heap allocating instructions. */ - [[nodiscard]] const std::set & + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use AllocaInstructions " + "instead")]] const std::set & getAllocaInstructions() const; /** * @brief Returns all Return and Resume Instructions. */ - [[nodiscard]] const std::set & + [[nodiscard]] [[deprecated( + "Getters are no longer needed. Use RetResInstructions " + "instead")]] const std::set & getRetResInstructions() const; + [[nodiscard]] nlohmann::json getAsJson() const; void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const; - - friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const GeneralStatistics &Statistics); }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const GeneralStatistics &Statistics); + /** * This class uses the Module Pass Mechanism of LLVM to compute * some statistics about a Module. This includes the number of diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 0b46a0c6fa..9d9b173435 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -24,9 +24,11 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include @@ -42,7 +44,7 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { static const std::set MemAllocatingFunctions = { "operator new(unsigned long)", "operator new[](unsigned long)", "malloc", "calloc", "realloc"}; - Stats.ModuleName = M.getName(); + Stats.ModuleName = M.getName().str(); for (auto &F : M) { ++Stats.Functions; for (auto &BB : F) { @@ -83,13 +85,21 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { if (llvm::isa(I)) { ++Stats.MemIntrinsics; } + if (llvm::isa(I)) { + ++Stats.NumInlineAsm; + } // check for function calls if (llvm::isa(I) || llvm::isa(I)) { ++Stats.CallSites; const llvm::CallBase *CallSite = llvm::cast(&I); - if (CallSite->getCalledFunction()) { - if (MemAllocatingFunctions.count(llvm::demangle( - CallSite->getCalledFunction()->getName().str()))) { + + const auto *CalledOp = + CallSite->getCalledOperand()->stripPointerCastsAndAliases(); + + if (const auto *CalleeFun = + llvm::dyn_cast(CalledOp)) { + if (MemAllocatingFunctions.count( + llvm::demangle(CalleeFun->getName().str()))) { // do not add allocas from llvm internal functions Stats.AllocaInstructions.insert(&I); ++Stats.AllocationSites; @@ -119,6 +129,8 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { } } } + } else { + ++Stats.IndCalls; } } } @@ -222,10 +234,13 @@ void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { nlohmann::json GeneralStatistics::getAsJson() const { nlohmann::json J; J["ModuleName"] = GeneralStatistics::ModuleName; - J["Instructions"] = getInstructions(); + J["Instructions"] = Instructions; J["Functions"] = Functions; J["AllocaInstructions"] = AllocaInstructions.size(); J["CallSites"] = CallSites; + J["IndirectCallSites"] = IndCalls; + J["MemoryIntrinsics"] = MemIntrinsics; + J["InlineAssembly"] = NumInlineAsm; J["GlobalVariables"] = Globals; J["Branches"] = Branches; J["GetElementPtrs"] = GetElementPtrs; @@ -236,23 +251,26 @@ nlohmann::json GeneralStatistics::getAsJson() const { return J; } -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const GeneralStatistics &Statistics) { - return OS << "General LLVM IR Statistics" - << "\n" +} // namespace psr + +llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, + const GeneralStatistics &Statistics) { + return OS << "General LLVM IR Statistics" << '\n' << "Module " << Statistics.ModuleName << ":\n" - << "LLVM IR instructions:\t" << Statistics.Instructions << "\n" - << "Functions:\t" << Statistics.Functions << "\n" - << "Global Variables:\t" << Statistics.Globals << "\n" - << "Global Variable Consts:\t" << Statistics.GlobalConsts << "\n" - << "Global Pointers:\t" << Statistics.GlobalPointers << "\n" + << "LLVM IR instructions:\t" << Statistics.Instructions << '\n' + << "Functions:\t\t" << Statistics.Functions << '\n' + << "Globals:\t\t" << Statistics.Globals << '\n' + << "Global Constants:\t" << Statistics.GlobalConsts << '\n' + << "Global Variables:\t" + << (Statistics.Globals - Statistics.GlobalConsts) << '\n' << "Alloca Instructions:\t" << Statistics.AllocaInstructions.size() - << "\n" - << "Call Sites:\t" << Statistics.CallSites << "\n" - << "Branches:\t" << Statistics.Branches << "\n" - << "GetElementPtrs:\t" << Statistics.GetElementPtrs << "\n" - << "Phi Nodes:\t" << Statistics.PhiNodes << "\n" - << "Basic Blocks:\t" << Statistics.BasicBlocks << "\n"; + << '\n' + << "Call Sites:\t\t" << Statistics.CallSites << '\n' + << "Indirect Call Sites:\t" << Statistics.IndCalls << '\n' + << "Memory Intrinsics:\t" << Statistics.MemIntrinsics << '\n' + << "Inline Assemblies:\t" << Statistics.NumInlineAsm << '\n' + << "Branches:\t" << Statistics.Branches << '\n' + << "GetElementPtrs:\t" << Statistics.GetElementPtrs << '\n' + << "Phi Nodes:\t" << Statistics.PhiNodes << '\n' + << "Basic Blocks:\t" << Statistics.BasicBlocks << '\n'; } - -} // namespace psr From 2fad1d63c6673023e0c321c87e8ea9348d09ccff Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 10:26:56 +0100 Subject: [PATCH 2/8] Even more stats --- .../Passes/GeneralStatisticsAnalysis.h | 7 +- .../Passes/GeneralStatisticsAnalysis.cpp | 92 +++++++++++++------ 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index a1d092c36c..920f38db3b 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -36,17 +36,22 @@ namespace psr { struct GeneralStatistics { size_t Functions = 0; + size_t ExternalFunctions = 0; + size_t FunctionDefinitions = 0; + size_t AddressTakenFunctions = 0; size_t Globals = 0; size_t BasicBlocks = 0; size_t AllocationSites = 0; size_t CallSites = 0; + size_t DebugIntrinsics = 0; size_t Instructions = 0; size_t StoreInstructions = 0; size_t LoadInstructions = 0; size_t MemIntrinsics = 0; - size_t GlobalPointers = 0; size_t Branches = 0; + size_t Switches = 0; size_t GetElementPtrs = 0; + size_t LandingPads = 0; size_t PhiNodes = 0; size_t GlobalConsts = 0; size_t NumInlineAsm = 0; diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 9d9b173435..5de09e4b66 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -16,8 +16,10 @@ #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/NlohmannLogging.h" #include "phasar/Utils/PAMMMacros.h" #include "llvm/Analysis/LoopInfo.h" @@ -25,6 +27,8 @@ #include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" @@ -33,20 +37,39 @@ #include -using namespace std; using namespace psr; namespace psr { +static bool isAddressTaken(const llvm::Function &Fun) noexcept { + for (const auto &Use : Fun.uses()) { + const auto *Call = llvm::dyn_cast(Use.getUser()); + if (!Call || Use.get() != Call->getCalledOperand()) { + return true; + } + } + return false; +} + llvm::AnalysisKey GeneralStatisticsAnalysis::Key; // NOLINT GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { PHASAR_LOG_LEVEL(INFO, "Running GeneralStatisticsAnalysis"); - static const std::set MemAllocatingFunctions = { - "operator new(unsigned long)", "operator new[](unsigned long)", "malloc", - "calloc", "realloc"}; + LLVMBasedCFG CFG; Stats.ModuleName = M.getName().str(); for (auto &F : M) { ++Stats.Functions; + + if (F.hasExternalLinkage()) { + ++Stats.ExternalFunctions; + } + if (!F.isDeclaration()) { + ++Stats.FunctionDefinitions; + } + + if (isAddressTaken(F)) { + ++Stats.AddressTakenFunctions; + } + for (auto &BB : F) { ++Stats.BasicBlocks; for (auto &I : BB) { @@ -66,6 +89,9 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { if (llvm::isa(I)) { ++Stats.Branches; } + if (llvm::isa(I)) { + ++Stats.Switches; + } if (llvm::isa(I)) { ++Stats.GetElementPtrs; } @@ -81,25 +107,29 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { if (llvm::isa(I)) { ++Stats.LoadInstructions; } + if (llvm::isa(I)) { + ++Stats.LandingPads; + } // check for llvm's memory intrinsics if (llvm::isa(I)) { ++Stats.MemIntrinsics; } - if (llvm::isa(I)) { - ++Stats.NumInlineAsm; + + if (llvm::isa(I)) { + ++Stats.DebugIntrinsics; } // check for function calls - if (llvm::isa(I) || llvm::isa(I)) { + if (const auto *CallSite = llvm::dyn_cast(&I)) { ++Stats.CallSites; - const llvm::CallBase *CallSite = llvm::cast(&I); const auto *CalledOp = CallSite->getCalledOperand()->stripPointerCastsAndAliases(); - if (const auto *CalleeFun = - llvm::dyn_cast(CalledOp)) { - if (MemAllocatingFunctions.count( - llvm::demangle(CalleeFun->getName().str()))) { + if (llvm::isa(CalledOp)) { + ++Stats.NumInlineAsm; + } else if (const auto *CalleeFun = + llvm::dyn_cast(CalledOp)) { + if (CFG.isHeapAllocatingFunction(CalleeFun)) { // do not add allocas from llvm internal functions Stats.AllocaInstructions.insert(&I); ++Stats.AllocationSites; @@ -138,9 +168,6 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { } // check for global pointers for (auto const &Global : M.globals()) { - if (Global.getType()->isPointerTy()) { - ++Stats.GlobalPointers; - } ++Stats.Globals; if (Global.isConstant()) { ++Stats.GlobalConsts; @@ -173,7 +200,6 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { PHASAR_LOG_LEVEL(INFO, "Calls Sites : " << Stats.CallSites); PHASAR_LOG_LEVEL(INFO, "Functions : " << Stats.Functions); PHASAR_LOG_LEVEL(INFO, "Globals : " << Stats.Globals); - PHASAR_LOG_LEVEL(INFO, "Global Pointer : " << Stats.GlobalPointers); PHASAR_LOG_LEVEL(INFO, "Global Consts : " << Stats.GlobalConsts); PHASAR_LOG_LEVEL(INFO, "Memory Intrinsics : " << Stats.MemIntrinsics); PHASAR_LOG_LEVEL(INFO, @@ -182,10 +208,7 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { INFO, "Allocated Types << " << Stats.AllocatedTypes.size()); for (const auto *Type : Stats.AllocatedTypes) { - std::string TypeStr; - llvm::raw_string_ostream Rso(TypeStr); - Type->print(Rso); - PHASAR_LOG_LEVEL(INFO, " " << Rso.str()); + PHASAR_LOG_LEVEL(INFO, " " << llvmTypeToString(Type)); }); // now we are done and can return the results return Stats; @@ -197,7 +220,7 @@ size_t GeneralStatistics::getFunctioncalls() const { return CallSites; } size_t GeneralStatistics::getInstructions() const { return Instructions; } -size_t GeneralStatistics::getGlobalPointers() const { return GlobalPointers; } +size_t GeneralStatistics::getGlobalPointers() const { return Globals; } size_t GeneralStatistics::getBasicBlocks() const { return BasicBlocks; } @@ -213,41 +236,46 @@ size_t GeneralStatistics::getStoreInstructions() const { return StoreInstructions; } -const set &GeneralStatistics::getAllocatedTypes() const { +const std::set & +GeneralStatistics::getAllocatedTypes() const { return AllocatedTypes; } -const set & +const std::set & GeneralStatistics::getAllocaInstructions() const { return AllocaInstructions; } -const set & +const std::set & GeneralStatistics::getRetResInstructions() const { return RetResInstructions; } void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { - OS << getAsJson().dump(4) << '\n'; + OS << getAsJson() << '\n'; } nlohmann::json GeneralStatistics::getAsJson() const { nlohmann::json J; - J["ModuleName"] = GeneralStatistics::ModuleName; + J["ModuleName"] = ModuleName; J["Instructions"] = Instructions; J["Functions"] = Functions; + J["ExternalFunctions"] = ExternalFunctions; + J["FunctionDefinitions"] = FunctionDefinitions; + J["AddressTakenFunctions"] = AddressTakenFunctions; J["AllocaInstructions"] = AllocaInstructions.size(); J["CallSites"] = CallSites; J["IndirectCallSites"] = IndCalls; J["MemoryIntrinsics"] = MemIntrinsics; + J["DebugIntrinsics"] = DebugIntrinsics; J["InlineAssembly"] = NumInlineAsm; J["GlobalVariables"] = Globals; J["Branches"] = Branches; J["GetElementPtrs"] = GetElementPtrs; J["BasicBlocks"] = BasicBlocks; J["PhiNodes"] = PhiNodes; + J["LandingPads"] = LandingPads; J["GlobalConsts"] = GlobalConsts; - J["GlobalPointers"] = GlobalPointers; return J; } @@ -259,6 +287,11 @@ llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, << "Module " << Statistics.ModuleName << ":\n" << "LLVM IR instructions:\t" << Statistics.Instructions << '\n' << "Functions:\t\t" << Statistics.Functions << '\n' + << "External Functions:\t" << Statistics.ExternalFunctions << '\n' + << "Function Definitions:\t" << Statistics.FunctionDefinitions + << '\n' + << "Address-Taken Functions:\t" << Statistics.AddressTakenFunctions + << '\n' << "Globals:\t\t" << Statistics.Globals << '\n' << "Global Constants:\t" << Statistics.GlobalConsts << '\n' << "Global Variables:\t" @@ -267,10 +300,13 @@ llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, << '\n' << "Call Sites:\t\t" << Statistics.CallSites << '\n' << "Indirect Call Sites:\t" << Statistics.IndCalls << '\n' - << "Memory Intrinsics:\t" << Statistics.MemIntrinsics << '\n' << "Inline Assemblies:\t" << Statistics.NumInlineAsm << '\n' + << "Memory Intrinsics:\t" << Statistics.MemIntrinsics << '\n' + << "Debug Intrinsics:\t" << Statistics.DebugIntrinsics << '\n' << "Branches:\t" << Statistics.Branches << '\n' + << "Switches:\t" << Statistics.Switches << '\n' << "GetElementPtrs:\t" << Statistics.GetElementPtrs << '\n' << "Phi Nodes:\t" << Statistics.PhiNodes << '\n' + << "LandingPads:\t" << Statistics.LandingPads << '\n' << "Basic Blocks:\t" << Statistics.BasicBlocks << '\n'; } From 3988972d067d0505d2eef178e5a761e1cfd28199 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 11:05:15 +0100 Subject: [PATCH 3/8] Some more counters --- .../Passes/GeneralStatisticsAnalysis.h | 10 +++ .../Passes/GeneralStatisticsAnalysis.cpp | 63 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index 920f38db3b..21f5de0334 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -56,6 +56,16 @@ struct GeneralStatistics { size_t GlobalConsts = 0; size_t NumInlineAsm = 0; size_t IndCalls = 0; + size_t TotalNumOperands = 0; + size_t TotalNumUses = 0; + size_t TotalNumPredecessorBBs = 0; + size_t TotalNumSuccessorBBs = 0; + size_t MaxNumOperands = 0; + size_t MaxNumUses = 0; + size_t MaxNumPredecessorBBs = 0; + size_t MaxNumSuccessorBBs = 0; + size_t NumInstWithMultipleUses = 0; + size_t NonVoidInsts = 0; std::set AllocatedTypes; std::set AllocaInstructions; std::set RetResInstructions; diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 5de09e4b66..95f6804351 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -25,6 +25,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Demangle/Demangle.h" #include "llvm/IR/AbstractCallSite.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstrTypes.h" @@ -33,6 +34,7 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include @@ -72,9 +74,44 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { for (auto &BB : F) { ++Stats.BasicBlocks; + + { + auto PredSize = llvm::pred_size(&BB); + auto SuccSize = llvm::succ_size(&BB); + Stats.TotalNumPredecessorBBs += PredSize; + Stats.TotalNumSuccessorBBs += SuccSize; + if (PredSize > Stats.MaxNumPredecessorBBs) { + ++Stats.MaxNumPredecessorBBs; + } + if (SuccSize > Stats.MaxNumSuccessorBBs) { + ++Stats.MaxNumSuccessorBBs; + } + } + for (auto &I : BB) { // found one more instruction ++Stats.Instructions; + + { + auto NumOps = I.getNumOperands(); + auto NumUses = I.getNumUses(); + Stats.TotalNumOperands += NumOps; + Stats.TotalNumUses += NumUses; + if (NumOps > Stats.MaxNumOperands) { + ++Stats.MaxNumOperands; + } + if (NumUses > Stats.MaxNumUses) { + ++Stats.MaxNumUses; + } + if (NumUses > 1) { + ++Stats.NumInstWithMultipleUses; + } + } + + if (!I.getType()->isVoidTy()) { + ++Stats.NonVoidInsts; + } + // check for alloca instruction for possible types if (const llvm::AllocaInst *Alloc = llvm::dyn_cast(&I)) { @@ -308,5 +345,29 @@ llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, << "GetElementPtrs:\t" << Statistics.GetElementPtrs << '\n' << "Phi Nodes:\t" << Statistics.PhiNodes << '\n' << "LandingPads:\t" << Statistics.LandingPads << '\n' - << "Basic Blocks:\t" << Statistics.BasicBlocks << '\n'; + << "Basic Blocks:\t" << Statistics.BasicBlocks << '\n' + << "Avg #pred per BasicBlock:\t" + << llvm::format("%g\n", double(Statistics.TotalNumPredecessorBBs) / + double(Statistics.BasicBlocks)) + << "Max #pred per BasicBlock:\t" << Statistics.MaxNumPredecessorBBs + << '\n' + << "Avg #succ per BasicBlock:\t" + << llvm::format("%g\n", double(Statistics.TotalNumSuccessorBBs) / + double(Statistics.BasicBlocks)) + << "Max #succ per BasicBlock:\t" << Statistics.MaxNumSuccessorBBs + << '\n' + << "Avg #operands per Inst:\t\t" + << llvm::format("%g\n", double(Statistics.TotalNumOperands) / + double(Statistics.Instructions)) + << "Max #operands per Inst:\t\t" << Statistics.MaxNumOperands + << '\n' + << "Avg #uses per Inst:\t\t" + << llvm::format("%g\n", double(Statistics.TotalNumUses) / + double(Statistics.Instructions)) + << "Max #uses per Inst:\t\t" << Statistics.MaxNumUses << '\n' + << "Insts with >1 uses:\t\t" << Statistics.NumInstWithMultipleUses + << '\n' + << "Non-void Insts:\t\t\t" << Statistics.NonVoidInsts << '\n' + + ; } From 29f35251a9c072868183fbe035abb42a297c5987 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 11:10:04 +0100 Subject: [PATCH 4/8] minor --- lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 95f6804351..95ff55f34f 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -7,13 +7,6 @@ * Philipp Schubert and others *****************************************************************************/ -/* - * MyHelloPass.cpp - * - * Created on: 05.07.2016 - * Author: pdschbrt - */ - #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" @@ -22,9 +15,6 @@ #include "phasar/Utils/NlohmannLogging.h" #include "phasar/Utils/PAMMMacros.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Demangle/Demangle.h" -#include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" @@ -39,8 +29,6 @@ #include -using namespace psr; - namespace psr { static bool isAddressTaken(const llvm::Function &Fun) noexcept { From a00a63a499c05a0d505466235d4b37669993c1a8 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 11:14:18 +0100 Subject: [PATCH 5/8] Make the GSA work again after the merge --- .../Passes/GeneralStatisticsAnalysis.cpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 95ff55f34f..3dfc21195c 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -214,27 +214,27 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { REG_COUNTER("GS Load Instructions", Stats.LoadInstructions, Full); // Using the logging guard explicitly since we are printing allocated types // manually - IF_LOG_ENABLED( - PHASAR_LOG_LEVEL(INFO, "GeneralStatisticsAnalysis summary for module: '" - << M.getName() << "'"); - PHASAR_LOG_LEVEL(INFO, "Instructions : " << Stats.Instructions); - PHASAR_LOG_LEVEL(INFO, - "Allocated Types : " << Stats.AllocatedTypes.size()); - PHASAR_LOG_LEVEL(INFO, "Allocation Sites : " << Stats.AllocationSites); - PHASAR_LOG_LEVEL(INFO, "Basic Blocks : " << Stats.BasicBlocks); - PHASAR_LOG_LEVEL(INFO, "Calls Sites : " << Stats.CallSites); - PHASAR_LOG_LEVEL(INFO, "Functions : " << Stats.Functions); - PHASAR_LOG_LEVEL(INFO, "Globals : " << Stats.Globals); - PHASAR_LOG_LEVEL(INFO, "Global Consts : " << Stats.GlobalConsts); - PHASAR_LOG_LEVEL(INFO, "Memory Intrinsics : " << Stats.MemIntrinsics); - PHASAR_LOG_LEVEL(INFO, - "Store Instructions : " << Stats.StoreInstructions); - PHASAR_LOG_LEVEL(INFO, ' '); PHASAR_LOG_LEVEL( - INFO, "Allocated Types << " << Stats.AllocatedTypes.size()); - for (const auto *Type - : Stats.AllocatedTypes) { - PHASAR_LOG_LEVEL(INFO, " " << llvmTypeToString(Type)); - }); + IF_LOG_LEVEL_ENABLED(INFO, { + PHASAR_LOG_LEVEL(INFO, "GeneralStatisticsAnalysis summary for module: '" + << M.getName() << "'"); + PHASAR_LOG_LEVEL(INFO, "Instructions : " << Stats.Instructions); + PHASAR_LOG_LEVEL(INFO, + "Allocated Types : " << Stats.AllocatedTypes.size()); + PHASAR_LOG_LEVEL(INFO, "Allocation Sites : " << Stats.AllocationSites); + PHASAR_LOG_LEVEL(INFO, "Basic Blocks : " << Stats.BasicBlocks); + PHASAR_LOG_LEVEL(INFO, "Calls Sites : " << Stats.CallSites); + PHASAR_LOG_LEVEL(INFO, "Functions : " << Stats.Functions); + PHASAR_LOG_LEVEL(INFO, "Globals : " << Stats.Globals); + PHASAR_LOG_LEVEL(INFO, "Global Consts : " << Stats.GlobalConsts); + PHASAR_LOG_LEVEL(INFO, "Memory Intrinsics : " << Stats.MemIntrinsics); + PHASAR_LOG_LEVEL(INFO, "Store Instructions : " << Stats.StoreInstructions); + PHASAR_LOG_LEVEL(INFO, ' '); + PHASAR_LOG_LEVEL(INFO, + "Allocated Types << " << Stats.AllocatedTypes.size()); + for (const auto *Type : Stats.AllocatedTypes) { + PHASAR_LOG_LEVEL(INFO, " " << llvmTypeToString(Type)); + } + }); // now we are done and can return the results return Stats; } From 8ad8611dbb3c0e7bd7f098424d6b4ae5a5cfc90b Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 11:26:24 +0100 Subject: [PATCH 6/8] More about globals --- .../Passes/GeneralStatisticsAnalysis.h | 4 +- .../Passes/GeneralStatisticsAnalysis.cpp | 59 +++++++++++-------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index 21f5de0334..0d1235cb68 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -40,6 +40,9 @@ struct GeneralStatistics { size_t FunctionDefinitions = 0; size_t AddressTakenFunctions = 0; size_t Globals = 0; + size_t GlobalConsts = 0; + size_t ExternalGlobals = 0; + size_t GlobalsDefinitions = 0; size_t BasicBlocks = 0; size_t AllocationSites = 0; size_t CallSites = 0; @@ -53,7 +56,6 @@ struct GeneralStatistics { size_t GetElementPtrs = 0; size_t LandingPads = 0; size_t PhiNodes = 0; - size_t GlobalConsts = 0; size_t NumInlineAsm = 0; size_t IndCalls = 0; size_t TotalNumOperands = 0; diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 3dfc21195c..96fc9a7db3 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -41,6 +41,29 @@ static bool isAddressTaken(const llvm::Function &Fun) noexcept { return false; } +template +static void collectAllocatedTypes(const llvm::CallBase *CallSite, Set &Into) { + for (const auto *User : CallSite->users()) { + if (const auto *Cast = llvm::dyn_cast(User)) { + if (Cast->getDestTy()->getPointerElementType()->isStructTy()) { + // finally check for ctor call + for (const auto *User : Cast->users()) { + if (llvm::isa(User) || + llvm::isa(User)) { + // potential call to the structures ctor + const auto *CTor = llvm::cast(User); + if (CTor->getCalledFunction() && + CTor->getCalledFunction()->getArg(0)->getType() == + Cast->getDestTy()) { + Into.insert(Cast->getDestTy()->getPointerElementType()); + } + } + } + } + } + } +} + llvm::AnalysisKey GeneralStatisticsAnalysis::Key; // NOLINT GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { PHASAR_LOG_LEVEL(INFO, "Running GeneralStatisticsAnalysis"); @@ -160,29 +183,7 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { ++Stats.AllocationSites; // check if an instance of a user-defined type is allocated on the // heap - for (auto *User : I.users()) { - if (auto *Cast = llvm::dyn_cast(User)) { - if (Cast->getDestTy() - ->getPointerElementType() - ->isStructTy()) { - // finally check for ctor call - for (auto *User : Cast->users()) { - if (llvm::isa(User) || - llvm::isa(User)) { - // potential call to the structures ctor - const llvm::CallBase *CTor = - llvm::cast(User); - if (CTor->getCalledFunction() && - CTor->getCalledFunction()->getArg(0)->getType() == - Cast->getDestTy()) { - Stats.AllocatedTypes.insert( - Cast->getDestTy()->getPointerElementType()); - } - } - } - } - } - } + collectAllocatedTypes(CallSite, Stats.AllocatedTypes); } } else { ++Stats.IndCalls; @@ -192,11 +193,17 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { } } // check for global pointers - for (auto const &Global : M.globals()) { + for (const auto &Global : M.globals()) { ++Stats.Globals; if (Global.isConstant()) { ++Stats.GlobalConsts; } + if (!Global.isDeclaration()) { + ++Stats.GlobalsDefinitions; + } + if (Global.hasExternalLinkage()) { + ++Stats.ExternalGlobals; + } } // register stuff in PAMM // For performance reasons (and out of sheer convenience) we simply initialize @@ -308,7 +315,7 @@ nlohmann::json GeneralStatistics::getAsJson() const { llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, const GeneralStatistics &Statistics) { - return OS << "General LLVM IR Statistics" << '\n' + return OS << "General LLVM IR Statistics\n" << "Module " << Statistics.ModuleName << ":\n" << "LLVM IR instructions:\t" << Statistics.Instructions << '\n' << "Functions:\t\t" << Statistics.Functions << '\n' @@ -321,6 +328,8 @@ llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, << "Global Constants:\t" << Statistics.GlobalConsts << '\n' << "Global Variables:\t" << (Statistics.Globals - Statistics.GlobalConsts) << '\n' + << "External Globals:\t" << Statistics.ExternalGlobals << '\n' + << "Global Definitions:\t" << Statistics.GlobalsDefinitions << '\n' << "Alloca Instructions:\t" << Statistics.AllocaInstructions.size() << '\n' << "Call Sites:\t\t" << Statistics.CallSites << '\n' From 1cca9451b66dc33ebfa60ce10ce9819347292dae Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 13:43:31 +0100 Subject: [PATCH 7/8] Formatting --- .../Passes/GeneralStatisticsAnalysis.h | 1 + .../Passes/GeneralStatisticsAnalysis.cpp | 129 +++++++++++------- 2 files changed, 79 insertions(+), 51 deletions(-) diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index 0d1235cb68..a33b6e10d8 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -67,6 +67,7 @@ struct GeneralStatistics { size_t MaxNumPredecessorBBs = 0; size_t MaxNumSuccessorBBs = 0; size_t NumInstWithMultipleUses = 0; + size_t NumInstsUsedOutsideBB = 0; size_t NonVoidInsts = 0; std::set AllocatedTypes; std::set AllocaInstructions; diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 96fc9a7db3..7cb897437e 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -24,10 +24,11 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include +#include namespace psr { @@ -123,6 +124,10 @@ GeneralStatistics GeneralStatisticsAnalysis::runOnModule(llvm::Module &M) { ++Stats.NonVoidInsts; } + if (I.isUsedOutsideOfBlock(I.getParent())) { + ++Stats.NumInstsUsedOutsideBB; + } + // check for alloca instruction for possible types if (const llvm::AllocaInst *Alloc = llvm::dyn_cast(&I)) { @@ -313,58 +318,80 @@ nlohmann::json GeneralStatistics::getAsJson() const { } // namespace psr +template struct AlignNum { + llvm::StringRef Name; + T Num; + + AlignNum(llvm::StringRef Name, T Num) noexcept : Name(Name), Num(Num) {} + AlignNum(llvm::StringRef Name, size_t Counter, size_t Numerator) noexcept + : Name(Name), Num(double(Counter) / double(Numerator)) {} + + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const AlignNum &AN) { + static constexpr size_t NumOffs = 32; + + auto Len = AN.Name.size() + 1; + auto Diff = -(Len < NumOffs) & (NumOffs - Len); + + OS << AN.Name << ':'; + // Default is two fixed-point decimal places, so shift the output by three + // spaces + OS.indent(Diff + std::is_floating_point_v * 3); + OS << llvm::formatv(" {0,+7}\n", AN.Num); + + return OS; + } +}; +template AlignNum(llvm::StringRef, T) -> AlignNum; +AlignNum(llvm::StringRef, size_t, size_t)->AlignNum; + llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, const GeneralStatistics &Statistics) { - return OS << "General LLVM IR Statistics\n" - << "Module " << Statistics.ModuleName << ":\n" - << "LLVM IR instructions:\t" << Statistics.Instructions << '\n' - << "Functions:\t\t" << Statistics.Functions << '\n' - << "External Functions:\t" << Statistics.ExternalFunctions << '\n' - << "Function Definitions:\t" << Statistics.FunctionDefinitions - << '\n' - << "Address-Taken Functions:\t" << Statistics.AddressTakenFunctions - << '\n' - << "Globals:\t\t" << Statistics.Globals << '\n' - << "Global Constants:\t" << Statistics.GlobalConsts << '\n' - << "Global Variables:\t" - << (Statistics.Globals - Statistics.GlobalConsts) << '\n' - << "External Globals:\t" << Statistics.ExternalGlobals << '\n' - << "Global Definitions:\t" << Statistics.GlobalsDefinitions << '\n' - << "Alloca Instructions:\t" << Statistics.AllocaInstructions.size() - << '\n' - << "Call Sites:\t\t" << Statistics.CallSites << '\n' - << "Indirect Call Sites:\t" << Statistics.IndCalls << '\n' - << "Inline Assemblies:\t" << Statistics.NumInlineAsm << '\n' - << "Memory Intrinsics:\t" << Statistics.MemIntrinsics << '\n' - << "Debug Intrinsics:\t" << Statistics.DebugIntrinsics << '\n' - << "Branches:\t" << Statistics.Branches << '\n' - << "Switches:\t" << Statistics.Switches << '\n' - << "GetElementPtrs:\t" << Statistics.GetElementPtrs << '\n' - << "Phi Nodes:\t" << Statistics.PhiNodes << '\n' - << "LandingPads:\t" << Statistics.LandingPads << '\n' - << "Basic Blocks:\t" << Statistics.BasicBlocks << '\n' - << "Avg #pred per BasicBlock:\t" - << llvm::format("%g\n", double(Statistics.TotalNumPredecessorBBs) / - double(Statistics.BasicBlocks)) - << "Max #pred per BasicBlock:\t" << Statistics.MaxNumPredecessorBBs - << '\n' - << "Avg #succ per BasicBlock:\t" - << llvm::format("%g\n", double(Statistics.TotalNumSuccessorBBs) / - double(Statistics.BasicBlocks)) - << "Max #succ per BasicBlock:\t" << Statistics.MaxNumSuccessorBBs - << '\n' - << "Avg #operands per Inst:\t\t" - << llvm::format("%g\n", double(Statistics.TotalNumOperands) / - double(Statistics.Instructions)) - << "Max #operands per Inst:\t\t" << Statistics.MaxNumOperands - << '\n' - << "Avg #uses per Inst:\t\t" - << llvm::format("%g\n", double(Statistics.TotalNumUses) / - double(Statistics.Instructions)) - << "Max #uses per Inst:\t\t" << Statistics.MaxNumUses << '\n' - << "Insts with >1 uses:\t\t" << Statistics.NumInstWithMultipleUses - << '\n' - << "Non-void Insts:\t\t\t" << Statistics.NonVoidInsts << '\n' + return OS + << "General LLVM IR Statistics\n" + << "Module " << Statistics.ModuleName << ":\n" + << "------------------------------------\n" + << AlignNum("LLVM IR instructions", Statistics.Instructions) + << AlignNum("Functions", Statistics.Functions) + << AlignNum("External Functions", Statistics.ExternalFunctions) + << AlignNum("Function Definitions", Statistics.FunctionDefinitions) + << AlignNum("Address-Taken Functions", + Statistics.AddressTakenFunctions) + << AlignNum("Globals", Statistics.Globals) + << AlignNum("Global Constants", Statistics.GlobalConsts) + << AlignNum("Global Variables", + Statistics.Globals - Statistics.GlobalConsts) + << AlignNum("External Globals", Statistics.ExternalGlobals) + << AlignNum("Global Definitions", Statistics.GlobalsDefinitions) + << AlignNum("Alloca Instructions", + Statistics.AllocaInstructions.size()) + << AlignNum("Call Sites", Statistics.CallSites) + << AlignNum("Indirect Call Sites", Statistics.IndCalls) + << AlignNum("Inline Assemblies", Statistics.NumInlineAsm) + << AlignNum("Memory Intrinsics", Statistics.MemIntrinsics) + << AlignNum("Debug Intrinsics", Statistics.DebugIntrinsics) + << AlignNum("Switches", Statistics.Switches) + << AlignNum("GetElementPtrs", Statistics.GetElementPtrs) + << AlignNum("Phi Nodes", Statistics.PhiNodes) + << AlignNum("LandingPads", Statistics.LandingPads) + << AlignNum("Basic Blocks", Statistics.BasicBlocks) + << AlignNum("Avg #pred per BasicBlock", + Statistics.TotalNumPredecessorBBs, Statistics.BasicBlocks) + << AlignNum("Max #pred per BasicBlock", + Statistics.MaxNumPredecessorBBs) + << AlignNum("Avg #succ per BasicBlock", + Statistics.TotalNumSuccessorBBs, Statistics.BasicBlocks) + << AlignNum("Max #succ per BasicBlock", Statistics.MaxNumSuccessorBBs) + << AlignNum("Avg #operands per Inst", Statistics.TotalNumOperands, + Statistics.Instructions) + << AlignNum("Max #operands per Inst", Statistics.MaxNumOperands) + << AlignNum("Avg #uses per Inst", Statistics.TotalNumUses, + Statistics.Instructions) + << AlignNum("Max #uses per Inst", Statistics.MaxNumUses) + << AlignNum("Insts with >1 uses", Statistics.NumInstWithMultipleUses) + << AlignNum("Non-void Insts", Statistics.NonVoidInsts) + << AlignNum("Insts used outside its BB", + Statistics.NumInstsUsedOutsideBB) ; } From 6e84ea3f4ecd87c1cebead59394d48abd38e2716 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 30 Nov 2023 13:49:47 +0100 Subject: [PATCH 8/8] minor --- lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 7cb897437e..4ba8409302 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -318,13 +318,14 @@ nlohmann::json GeneralStatistics::getAsJson() const { } // namespace psr +namespace { template struct AlignNum { llvm::StringRef Name; T Num; AlignNum(llvm::StringRef Name, T Num) noexcept : Name(Name), Num(Num) {} - AlignNum(llvm::StringRef Name, size_t Counter, size_t Numerator) noexcept - : Name(Name), Num(double(Counter) / double(Numerator)) {} + AlignNum(llvm::StringRef Name, size_t Numerator, size_t Denominator) noexcept + : Name(Name), Num(double(Numerator) / double(Denominator)) {} friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const AlignNum &AN) { @@ -337,20 +338,21 @@ template struct AlignNum { // Default is two fixed-point decimal places, so shift the output by three // spaces OS.indent(Diff + std::is_floating_point_v * 3); - OS << llvm::formatv(" {0,+7}\n", AN.Num); + OS << llvm::formatv("{0,+7}\n", AN.Num); return OS; } }; template AlignNum(llvm::StringRef, T) -> AlignNum; AlignNum(llvm::StringRef, size_t, size_t)->AlignNum; +} // namespace llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, const GeneralStatistics &Statistics) { return OS << "General LLVM IR Statistics\n" << "Module " << Statistics.ModuleName << ":\n" - << "------------------------------------\n" + << "---------------------------------------\n" << AlignNum("LLVM IR instructions", Statistics.Instructions) << AlignNum("Functions", Statistics.Functions) << AlignNum("External Functions", Statistics.ExternalFunctions)