Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jlm/llvm/Makefile.sub
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ libllvm_SOURCES = \
jlm/llvm/opt/alias-analyses/Andersen.cpp \
jlm/llvm/opt/alias-analyses/LocalAliasAnalysis.cpp \
jlm/llvm/opt/alias-analyses/MemoryStateEncoder.cpp \
jlm/llvm/opt/alias-analyses/ModRefSummary.cpp \
jlm/llvm/opt/alias-analyses/PointerObjectSet.cpp \
jlm/llvm/opt/alias-analyses/PointsToAnalysisStateEncoder.cpp \
jlm/llvm/opt/alias-analyses/PointsToGraph.cpp \
Expand Down
9 changes: 9 additions & 0 deletions jlm/llvm/opt/alias-analyses/AgnosticModRefSummarizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ AgnosticModRefSummarizer::SummarizeModRefs(
AnnotateRegion(rvsdgModule.Rvsdg().GetRootRegion());

statistics->StopCollecting();

// Perform the collection of the memory state distribution AFTER we invoked StopCollecting() such
// that it does not count into the timing measurements
if (statisticsCollector.IsDemanded(statistics->GetId()))
{
const auto summaries = collectMemoryStateDistribution(rvsdgModule.Rvsdg(), *ModRefSummary_);
statistics->addMemoryStateDistribution(summaries);
}

statisticsCollector.CollectDemandedStatistics(std::move(statistics));

return std::move(ModRefSummary_);
Expand Down
8 changes: 8 additions & 0 deletions jlm/llvm/opt/alias-analyses/AgnosticModRefSummarizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class AgnosticModRefSummarizer final : public ModRefSummarizer
*/
class AgnosticModRefSummarizer::Statistics final : public util::Statistics
{
static constexpr auto memoryStateDistributionLabel_ = "MemoryStateDistribution";

public:
Statistics(
const util::FilePath & sourceFile,
Expand Down Expand Up @@ -166,6 +168,12 @@ class AgnosticModRefSummarizer::Statistics final : public util::Statistics
GetTimer(Label::Timer).stop();
}

void
addMemoryStateDistribution(const std::vector<MemoryStateSummary> & memoryStateDistribution)
{
AddMeasurement(memoryStateDistributionLabel_, toString(memoryStateDistribution));
}

static std::unique_ptr<Statistics>
Create(
const util::FilePath & sourceFile,
Expand Down
23 changes: 14 additions & 9 deletions jlm/llvm/opt/alias-analyses/AgnosticModRefSummarizerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,27 +825,32 @@ TEST(AgnosticModRefSummarizerTests, TestMemcpy)

TEST(AgnosticModRefSummarizerTests, TestStatistics)
{
using namespace jlm::llvm;
using namespace jlm::llvm::aa;
using namespace jlm::util;

// Arrange
jlm::llvm::LoadTest1 test;
LoadTest1 test;
auto pointsToGraph = RunAndersen(test.module());

jlm::util::StatisticsCollectorSettings statisticsCollectorSettings(
{ jlm::util::Statistics::Id::AgnosticModRefSummarizer });
jlm::util::StatisticsCollector statisticsCollector(statisticsCollectorSettings);
StatisticsCollectorSettings statisticsCollectorSettings(
{ Statistics::Id::AgnosticModRefSummarizer });
StatisticsCollector statisticsCollector(statisticsCollectorSettings);

// Act
jlm::llvm::aa::AgnosticModRefSummarizer::Create(
test.module(),
*pointsToGraph,
statisticsCollector);
AgnosticModRefSummarizer::Create(test.module(), *pointsToGraph, statisticsCollector);

// Assert
EXPECT_EQ(statisticsCollector.NumCollectedStatistics(), 1u);

auto & statistics = dynamic_cast<const jlm::llvm::aa::AgnosticModRefSummarizer::Statistics &>(
auto & statistics = dynamic_cast<const AgnosticModRefSummarizer::Statistics &>(
*statisticsCollector.CollectedStatistics().begin());

EXPECT_EQ(statistics.GetSourceFile(), test.module().SourceFileName());
EXPECT_EQ(statistics.NumPointsToGraphMemoryNodes(), 2u);
EXPECT_NE(statistics.GetTime(), 0u);
EXPECT_EQ(
statistics.GetMeasurementValue<std::string>("MemoryStateDistribution"),
"LAMBDA[f]-LAMBDA[f]-(0:0)-2-2,LAMBDA[f]-Load[ptr]-(1:0)-2-2,LAMBDA[f]-Load[bit32]-(1:1)-2-"
"2");
}
181 changes: 181 additions & 0 deletions jlm/llvm/opt/alias-analyses/ModRefSummary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright 2026 Nico Reißmann <nico.reissmann@gmail.com>
* See COPYING for terms of redistribution.
*/

#include <jlm/llvm/ir/operators/alloca.hpp>
#include <jlm/llvm/ir/operators/call.hpp>
#include <jlm/llvm/ir/operators/Load.hpp>
#include <jlm/llvm/ir/operators/operators.hpp>
#include <jlm/llvm/ir/operators/StdLibIntrinsicOperations.hpp>
#include <jlm/llvm/ir/operators/Store.hpp>
#include <jlm/llvm/opt/alias-analyses/ModRefSummary.hpp>
#include <jlm/rvsdg/MatchType.hpp>
#include <jlm/rvsdg/Phi.hpp>

namespace jlm::llvm::aa
{

std::vector<MemoryStateSummary>
collectMemoryStateDistribution(const rvsdg::Graph & rvsdg, const ModRefSummary & modRefSummary)
{
std::function<
void(const rvsdg::Region &, const rvsdg::LambdaNode *, std::vector<MemoryStateSummary> &)>
collect = [&](const rvsdg::Region & region,
const rvsdg::LambdaNode * lambdaNode,
std::vector<MemoryStateSummary> & summaries)
{
for (auto & node : region.Nodes())
{
rvsdg::MatchTypeOrFail(
node,
[&](const rvsdg::PhiNode & phiNode)
{
JLM_ASSERT(lambdaNode == nullptr);
collect(*phiNode.subregion(), lambdaNode, summaries);
},
[&](const rvsdg::DeltaNode &)
{
JLM_ASSERT(lambdaNode == nullptr);
// Nothing needs to be done
},
[&](const rvsdg::LambdaNode & n)
{
JLM_ASSERT(lambdaNode == nullptr);
auto entrySize = modRefSummary.GetLambdaEntryModRef(n).getModRefNodes().size();
auto exitSize = modRefSummary.GetLambdaExitModRef(n).getModRefNodes().size();
summaries.push_back({ &n, &n, entrySize, exitSize });

collect(*n.subregion(), &n, summaries);
},
[&](const rvsdg::ThetaNode & thetaNode)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetThetaModRef(thetaNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &thetaNode, size, size });

collect(*thetaNode.subregion(), lambdaNode, summaries);
},
[&](const rvsdg::GammaNode & gammaNode)
{
JLM_ASSERT(lambdaNode != nullptr);
auto entrySize = modRefSummary.GetGammaEntryModRef(gammaNode).getModRefNodes().size();
auto exitSize = modRefSummary.GetGammaExitModRef(gammaNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &gammaNode, entrySize, exitSize });

for (auto & subregion : gammaNode.Subregions())
collect(subregion, lambdaNode, summaries);
},
[&](const rvsdg::SimpleNode & simpleNode)
{
MatchTypeWithDefault(
simpleNode.GetOperation(),
[&](const StoreOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const LoadOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const MemCpyOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const MemMoveOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const MemSetOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const FreeOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const AllocaOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const MallocOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const CallOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
auto size = modRefSummary.GetSimpleNodeModRef(simpleNode).getModRefNodes().size();
summaries.push_back({ lambdaNode, &simpleNode, size, size });
},
[&](const MemoryStateOperation &)
{
JLM_ASSERT(lambdaNode != nullptr);
// Nothing needs to be done
},
[&]()
{
// Any remaining type of node should not involve any memory states
JLM_ASSERT(!hasMemoryState(node));
});
});
}
};

std::vector<MemoryStateSummary> summaries;
collect(rvsdg.GetRootRegion(), nullptr, summaries);
return summaries;
}

std::string
toString(const std::vector<MemoryStateSummary> & memoryStateDistribution)
{
auto toString = [](const MemoryStateSummary & memoryStateSummary)
{
constexpr char separator = '-';
return util::strfmt(
memoryStateSummary.lambdaNode->DebugString(),
separator,
memoryStateSummary.node->DebugString(),
separator,
"(",
memoryStateSummary.node->region()->getRegionId(),
":",
memoryStateSummary.node->GetNodeId(),
")",
separator,
memoryStateSummary.numMemoryInputStates,
separator,
memoryStateSummary.numMemoryOutputStates);
};

size_t n = 0;
std::string summaryStr;
for (auto & summary : memoryStateDistribution)
{
summaryStr += toString(summary);
if (n != memoryStateDistribution.size() - 1)
summaryStr += ",";
n++;
}

return summaryStr;
}

}
25 changes: 25 additions & 0 deletions jlm/llvm/opt/alias-analyses/ModRefSummary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,31 @@ class ModRefSummary
GetLambdaExitModRef(const rvsdg::LambdaNode & lambda) const = 0;
};

struct MemoryStateSummary
{
MemoryStateSummary(
const rvsdg::LambdaNode * lambdaNode,
const rvsdg::Node * node,
const size_t numMemoryInputStates,
const size_t numMemoryOutputStates)
: lambdaNode(lambdaNode),
node(node),
numMemoryInputStates(numMemoryInputStates),
numMemoryOutputStates(numMemoryOutputStates)
{}

const rvsdg::LambdaNode * lambdaNode = nullptr;
const rvsdg::Node * node = nullptr;
size_t numMemoryInputStates = 0;
size_t numMemoryOutputStates = 0;
};

std::vector<MemoryStateSummary>
collectMemoryStateDistribution(const rvsdg::Graph & rvsdg, const ModRefSummary & modRefSummary);

std::string
toString(const std::vector<MemoryStateSummary> & memoryStateDistribution);

}

#endif // JLM_LLVM_OPT_ALIAS_ANALYSES_MODREFSUMMARY_HPP
16 changes: 16 additions & 0 deletions jlm/llvm/opt/alias-analyses/RegionAwareModRefSummarizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ class RegionAwareModRefSummarizer::Statistics final : public util::Statistics
static constexpr auto ReadOnlyDetectionTimer_ = "ReadOnlyDetectionTimer";
static constexpr auto ModRefSetMaterializationTimer_ = "ModRefSetMaterializationTimer";

static constexpr auto memoryStateDistributionLabel_ = "MemoryStateDistribution";

public:
~Statistics() override = default;

Expand Down Expand Up @@ -202,6 +204,12 @@ class RegionAwareModRefSummarizer::Statistics final : public util::Statistics
AddMeasurement(ModRefSetSizeAfterMaterializationLabel_, modRefSetSizeAfterMaterialization);
}

void
addMemoryStateDistribution(const std::vector<MemoryStateSummary> & memoryStateDistribution)
{
AddMeasurement(memoryStateDistributionLabel_, toString(memoryStateDistribution));
}

static std::unique_ptr<Statistics>
Create(const rvsdg::RvsdgModule & rvsdgModule, const PointsToGraph & pointsToGraph)
{
Expand Down Expand Up @@ -897,6 +905,14 @@ RegionAwareModRefSummarizer::SummarizeModRefs(
Context_->numModRefSetsCallingExternalFunction,
Context_->modRefSetSizeAfterMaterialization);

// Perform the collection of the memory state distribution AFTER we invoked stopped collecting
// everything such that it does not count into the timing measurements
if (statisticsCollector.IsDemanded(statistics->GetId()))
{
const auto distribution = collectMemoryStateDistribution(rvsdgModule.Rvsdg(), *ModRefSummary_);
statistics->addMemoryStateDistribution(distribution);
}

statisticsCollector.CollectDemandedStatistics(std::move(statistics));
Context_.reset();
return std::move(ModRefSummary_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,13 @@ TEST(RegionAwareModRefSummarizerTests, TestStatistics)
EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#SimpleAllocas"), 5u);
EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#Functions"), 1u);
EXPECT_EQ(statistics.GetMeasurementValue<uint64_t>("#FunctionsCallingSetjmp"), 0u);
EXPECT_EQ(
statistics.GetMeasurementValue<std::string>("MemoryStateDistribution"),
"LAMBDA[f]-LAMBDA[f]-(0:0)-0-0,LAMBDA[f]-ALLOCA[bit32]-(1:1)-1-1,LAMBDA[f]-ALLOCA[bit32]-(1:"
"2)-1-1,LAMBDA[f]-ALLOCA[ptr]-(1:3)-1-1,LAMBDA[f]-ALLOCA[ptr]-(1:4)-1-1,LAMBDA[f]-ALLOCA[ptr]"
"-(1:5)-1-1,LAMBDA[f]-Store[ptr]-(1:11)-1-1,LAMBDA[f]-Store[ptr]-(1:12)-1-1,LAMBDA[f]-Store["
"ptr]-(1:13)-1-1,LAMBDA[f]-Load[ptr]-(1:14)-1-1,LAMBDA[f]-Load[ptr]-(1:15)-1-1,LAMBDA[f]-"
"Store[ptr]-(1:16)-1-1");

EXPECT_TRUE(statistics.HasTimer("SimpleAllocasSetTimer"));
EXPECT_TRUE(statistics.HasTimer("AnnotationTimer"));
Expand Down
Loading