36#include <unordered_map>
46 !std::getenv(
"JLM_DISABLE_NON_REENTRANT_ALLOCA_BLOCKLIST");
54 !std::getenv(
"JLM_DISABLE_OPERATION_SIZE_BLOCKING");
61 !std::getenv(
"JLM_DISABLE_CONSTANT_MEMORY_BLOCKING");
74 !std::getenv(
"JLM_DISABLE_CALL_SIMPLE_ALLOCA_BLOCKING");
94 "ModRefSetSizeBeforeMaterialization";
98 "#ModRefSetsCallingExternalFunction";
100 "ModRefSetSizeAfterMaterialization";
209 size_t numModRefSetsMaterialized,
210 size_t modRefSetSizeBeforeMaterialization,
211 size_t modRefSetSizeAfterFiltering,
212 size_t numModRefSetsWithEffectOnExternal,
213 size_t numModRefSetsCallingExternalFunction,
214 size_t modRefSetSizeAfterMaterialization)
223 numModRefSetsCallingExternalFunction);
227 static std::unique_ptr<Statistics>
230 return std::make_unique<Statistics>(rvsdgModule, pointsToGraph);
252 static constexpr uint32_t
NoneSize = std::numeric_limits<uint32_t>::max();
265 [[nodiscard]] std::optional<size_t>
282 [[nodiscard]] std::optional<size_t>
299 minSize = std::min<size_t>(minSize,
NoneSize - 1);
318 minSize = std::min<size_t>(minSize,
NoneSize - 1);
391 const auto [it, inserted] =
modRefNodes_.insert({ memoryNode, modRefEffect });
396 auto oldEffects = it->second;
397 it->second = oldEffects | modRefEffect;
398 return it->second != oldEffects;
414 bool isExternallyAvailable,
415 std::optional<size_t> memoryNodeSize,
421 if (isExternallyAvailable)
577 .
addMemoryNode(ptgNode, isExternallyAvailable, memoryNodeSize, modRefEffect);
624 const auto it =
nodeMap_.find(&node);
638 auto [it, inserted] =
nodeMap_.insert({ &node, 0 });
642 it->second = created;
650 [[nodiscard]]
const std::vector<ModRefSetIndex> &
656 [[nodiscard]] std::string
660 std::stringstream ss;
661 ss <<
"{MRS#" << index <<
"; ";
662 const auto mayRefMinSize = modRefSet.getRefExternalMinSize();
663 if (mayRefMinSize.has_value())
664 ss <<
"RefExt>=" << *mayRefMinSize <<
" bytes; ";
665 const auto mayModMinSize = modRefSet.getModExternalMinSize();
666 if (mayModMinSize.has_value())
667 ss <<
"ModExt>=" << *mayModMinSize <<
" bytes; ";
668 if (modRefSet.mayCallExternalFunction())
669 ss <<
"MayCallExt; ";
672 for (
auto [memoryNode, modRefEffect] : modRefSet.getModRefNodes())
680 switch (modRefEffect)
735 [[nodiscard]]
static std::unique_ptr<RegionAwareModRefSummary>
738 return std::make_unique<RegionAwareModRefSummary>(pointsToGraph);
773 std::unordered_map<const rvsdg::Node *, ModRefSetIndex>
nodeMap_;
844 std::unordered_map<const rvsdg::Node *, util::HashSet<PointsToGraph::NodeIndex>>
867 std::unordered_map<ModRefSetIndex, const util::HashSet<PointsToGraph::NodeIndex> *>
915 const rvsdg::RvsdgModule & rvsdgModule,
920 Context_ = std::make_unique<Context>(pointsToGraph);
921 auto statistics = Statistics::Create(rvsdgModule, pointsToGraph);
923 statistics->startCallGraphStatistics();
924 createCallGraph(rvsdgModule);
925 statistics->stopCallGraphStatistics(
926 Context_->SccFunctions.size(),
927 Context_->FunctionsCallingSetjmp.Size());
929 statistics->StartCreateSimpleAllocasSetStatistics();
930 Context_->SimpleAllocas = CreateSimpleAllocaSet(pointsToGraph);
931 statistics->StopCreateSimpleAllocasSetStatistics(Context_->SimpleAllocas.Size());
933 statistics->StartCreateNonReentrantAllocaSetsStatistics();
934 auto numNonReentrantAllocas = CreateNonReentrantAllocaSets();
935 statistics->StopCreateNonReentrantAllocaSetsStatistics(numNonReentrantAllocas);
937 statistics->StartAnnotationStatistics();
939 for (
const auto & scc : Context_->SccFunctions)
941 for (
const auto lambda : scc.Items())
943 AnnotateFunction(*lambda);
946 statistics->StopAnnotationStatistics();
948 statistics->StartSolvingStatistics();
949 SolveModRefSetConstraintGraph();
950 statistics->StopSolvingStatistics();
962 statistics->startReadOnlyMemoryDetectionStatistics();
963 determineReadOnlyMemory();
964 statistics->stopReadOnlyMemoryDetectionStatistics(Context_->ReadOnlyMemoryNodes.Size());
967 statistics->startModRefSetMaterializationStatistics();
969 statistics->stopModRefSetMaterializationStatistics(
970 Context_->numModRefSetsMaterialized,
971 Context_->modRefSetSizeBeforeMaterialization,
972 Context_->modRefSetSizeAfterFiltering,
973 Context_->numModRefSetsWithEffectOnExternal,
974 Context_->numModRefSetsCallingExternalFunction,
975 Context_->modRefSetSizeAfterMaterialization);
986 return std::move(ModRefSummary_);
994static std::vector<const rvsdg::LambdaNode *>
997 std::vector<const rvsdg::LambdaNode *> result;
1000 const std::function<void(
rvsdg::Region &)> CollectLambdasInRegion =
1003 for (
auto & node : region.Nodes())
1007 result.push_back(lambda);
1011 for (
size_t i = 0; i < structural->nsubregions(); i++)
1013 CollectLambdasInRegion(*structural->subregion(i));
1027 const auto & pointsToGraph =
Context_->pointsToGraph;
1033 std::unordered_map<const rvsdg::LambdaNode *, size_t> callGraphNodeIndex;
1034 callGraphNodeIndex.reserve(lambdaNodes.size());
1035 for (
size_t i = 0; i < lambdaNodes.size(); i++)
1037 callGraphNodeIndex.insert({ lambdaNodes[i], i });
1041 const auto externalNodeIndex = lambdaNodes.size();
1042 const auto numCallGraphNodes = externalNodeIndex + 1;
1045 std::vector<util::HashSet<size_t>> callGraphSuccessors(numCallGraphNodes);
1048 const auto handleCall = [&](
const rvsdg::SimpleNode & callNode,
size_t callerIndex) ->
void
1051 if (classification->isSetjmpCall())
1053 Context_->FunctionsCallingSetjmp.insert(lambdaNodes[callerIndex]);
1058 const auto targetPtgNode = pointsToGraph.getNodeForRegister(*target);
1061 for (
const auto calleePtgNode : pointsToGraph.getExplicitTargets(targetPtgNode).Items())
1063 const auto kind = pointsToGraph.getNodeKind(calleePtgNode);
1066 const auto & lambdaNode = pointsToGraph.getLambdaForNode(calleePtgNode);
1069 JLM_ASSERT(callGraphNodeIndex.find(&lambdaNode) != callGraphNodeIndex.end());
1070 const auto calleeCallGraphNode = callGraphNodeIndex[&lambdaNode];
1073 callGraphSuccessors[callerIndex].insert(calleeCallGraphNode);
1078 callGraphSuccessors[callerIndex].insert(externalNodeIndex);
1082 if (pointsToGraph.isTargetingAllExternallyAvailable(targetPtgNode))
1085 callGraphSuccessors[callerIndex].insert(externalNodeIndex);
1090 const std::function<void(
const rvsdg::Region &,
size_t)> handleCalls =
1091 [&](
const rvsdg::Region & region,
size_t callerIndex) ->
void
1093 for (
auto & node : region.
Nodes())
1098 handleCall(*callNode, callerIndex);
1105 for (
auto & subregion : structural.
Subregions())
1107 handleCalls(subregion, callerIndex);
1114 for (
size_t i = 0; i < lambdaNodes.size(); i++)
1116 handleCalls(*lambdaNodes[i]->subregion(), i);
1119 if (pointsToGraph.isExternallyAvailable(pointsToGraph.getNodeForLambda(*lambdaNodes[i])))
1121 callGraphSuccessors[externalNodeIndex].insert(i);
1126 callGraphSuccessors[externalNodeIndex].insert(externalNodeIndex);
1129 const auto getSuccessors = [&](
size_t nodeIndex)
1131 return callGraphSuccessors[nodeIndex].Items();
1135 std::vector<size_t> sccIndex;
1136 std::vector<size_t> reverseTopologicalOrder;
1137 auto numSCCs = util::FindStronglyConnectedComponents<size_t>(
1141 reverseTopologicalOrder);
1145 Context_->SccFunctions.resize(numSCCs);
1146 for (
size_t i = 0; i < lambdaNodes.size(); i++)
1148 Context_->SccFunctions[sccIndex[i]].insert(lambdaNodes[i]);
1149 Context_->FunctionToSccIndex[lambdaNodes[i]] = sccIndex[i];
1153 Context_->SccCallTargets.resize(numSCCs);
1154 for (
size_t i = 0; i < numCallGraphNodes; i++)
1156 for (
auto target : callGraphSuccessors[i].Items())
1158 Context_->SccCallTargets[sccIndex[i]].insert(sccIndex[target]);
1163 Context_->ExternalNodeSccIndex = sccIndex[externalNodeIndex];
1172 std::queue<PointsToGraph::NodeIndex> notSimple;
1183 simpleAllocas.
insert(ptgNode);
1185 notSimple.push(ptgNode);
1189 while (!notSimple.empty())
1191 const auto ptgNode = notSimple.front();
1198 if (simpleAllocas.
Remove(targetPtgNode))
1199 notSimple.push(targetPtgNode);
1203 return simpleAllocas;
1209 const auto & pointsToGraph =
Context_->pointsToGraph;
1213 while (!
nodes.empty())
1215 const auto ptgNode =
nodes.front();
1218 for (
const auto targetPtgNode : pointsToGraph.getExplicitTargets(ptgNode).Items())
1221 if (!
Context_->SimpleAllocas.Contains(targetPtgNode))
1224 if (reachableSimpleAllocas.
insert(targetPtgNode))
1225 nodes.push(targetPtgNode);
1229 return reachableSimpleAllocas;
1236 const auto & pointsToGraph =
Context_->pointsToGraph;
1239 std::queue<PointsToGraph::NodeIndex>
nodes;
1240 for (
auto argument : region.
Arguments())
1244 const auto ptgNode = pointsToGraph.getNodeForRegister(*argument);
1245 nodes.push(ptgNode);
1255 const auto & pointsToGraph =
Context_->pointsToGraph;
1258 std::queue<PointsToGraph::NodeIndex>
nodes;
1260 for (
size_t i = 0; i < numArguments; i++)
1266 const auto ptgNode = pointsToGraph.getNodeForRegister(argument);
1267 nodes.push(ptgNode);
1276 const auto scc =
Context_->FunctionToSccIndex[&lambda];
1277 return Context_->SccCallTargets[scc].Contains(scc);
1283 const auto & pointsToGraph =
Context_->pointsToGraph;
1286 std::unordered_map<const rvsdg::Region *, util::HashSet<PointsToGraph::NodeIndex>>
1287 reachableSimpleAllocas;
1293 if (
const auto it = reachableSimpleAllocas.find(®ion); it != reachableSimpleAllocas.end())
1303 auto & allocaNode = pointsToGraph.getAllocaForNode(simpleAllocaPtgNode);
1304 const auto & region = *allocaNode.region();
1308 const auto & lambda = getSurroundingLambdaNode(allocaNode);
1321 size_t numNonReentrantAllocas = 0;
1324 for (
auto simpleAllocaPtgNode :
Context_->SimpleAllocas.Items())
1326 if (!isNonReentrant(simpleAllocaPtgNode))
1329 const auto & region = *pointsToGraph.getAllocaForNode(simpleAllocaPtgNode).region();
1330 const auto structuralNode = region.node();
1332 Context_->NonReentrantAllocas[structuralNode].insert(simpleAllocaPtgNode);
1333 numNonReentrantAllocas++;
1336 return numNonReentrantAllocas;
1346 Context_->ModRefSetSimpleConstraints[from].insert(to);
1355 Context_->ModRefSetBlocklists[index] = &blocklist;
1363 if (
Context_->FunctionsCallingSetjmp.Contains(&lambda))
1374 const auto lambdaPtgNode =
Context_->pointsToGraph.getNodeForLambda(lambda);
1375 if (
Context_->pointsToGraph.isExternallyAvailable(lambdaPtgNode))
1387 for (
auto & node : region.
Nodes())
1410 const auto modRefSet =
ModRefSummary_->getOrCreateSetForNode(structuralNode, lambda);
1412 for (
auto & subregion : structuralNode.
Subregions())
1418 if (
const auto it =
Context_->NonReentrantAllocas.find(&structuralNode);
1427std::optional<ModRefSetIndex>
1432 return MatchTypeWithDefault(
1436 return AnnotateLoad(simpleNode, lambda);
1440 return AnnotateStore(simpleNode, lambda);
1444 return AnnotateAlloca(simpleNode, lambda);
1448 return AnnotateMalloc(simpleNode, lambda);
1452 return AnnotateFree(simpleNode, lambda);
1456 return AnnotateMemcpy(simpleNode, lambda);
1460 return AnnotateMemset(simpleNode, lambda);
1464 return AnnotateMemmove(simpleNode, lambda);
1468 return AnnotateCall(simpleNode, lambda);
1473 return std::nullopt;
1475 [&]() -> std::optional<ModRefSetIndex>
1478 JLM_ASSERT(!hasMemoryState(simpleNode));
1479 return std::nullopt;
1487 std::optional<size_t> minTargetSize,
1490 const auto & pointsToGraph =
Context_->pointsToGraph;
1492 const auto registerPtgNode = pointsToGraph.getNodeForRegister(origin);
1500 const auto targetSize = pointsToGraph.tryGetNodeSize(targetPtgNode);
1501 if (targetSize.has_value() && *targetSize < minTargetSize)
1504 ModRefSummary_->addExplicitMemoryNodeToSet(modRefSetIndex, targetPtgNode, modRefEffect);
1508 if (pointsToGraph.isTargetingAllExternallyAvailable(registerPtgNode))
1512 ModRefSummary_->markSetAsReferencingExternal(modRefSetIndex, minTargetSize.value_or(0));
1516 ModRefSummary_->markSetAsModifyingExternal(modRefSetIndex, minTargetSize.value_or(0));
1520 for (
const auto targetPtgNode : pointsToGraph.getExplicitTargets(registerPtgNode).Items())
1524 !pointsToGraph.isTargetingAllExternallyAvailable(registerPtgNode)
1525 || !pointsToGraph.isExternallyAvailable(targetPtgNode));
1526 tryAddToModRefSet(targetPtgNode);
1535 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(loadNode, lambda);
1537 const auto loadOperation = util::assertedCast<const LoadOperation>(&loadNode.
GetOperation());
1549 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(storeNode, lambda);
1551 const auto storeOperation = util::assertedCast<const StoreOperation>(&storeNode.
GetOperation());
1563 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(allocaNode, lambda);
1564 const auto allocaMemoryNode =
Context_->pointsToGraph.getNodeForAlloca(allocaNode);
1576 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(mallocNode, lambda);
1577 const auto mallocMemoryNode =
Context_->pointsToGraph.getNodeForMalloc(mallocNode);
1591 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(freeNode, lambda);
1606 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(memcpyNode, lambda);
1623 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(memmoveNode, lambda);
1640 const auto nodeModRef =
ModRefSummary_->getOrCreateSetForNode(memsetNode, lambda);
1656 const auto & pointsToGraph =
Context_->pointsToGraph;
1659 const auto callModRef =
ModRefSummary_->getOrCreateSetForNode(callNode, lambda);
1662 const auto targetPtr = callNode.
input(0)->
origin();
1663 const auto targetPtgNode =
Context_->pointsToGraph.getNodeForRegister(*targetPtr);
1666 for (
const auto calleePtgNode : pointsToGraph.getExplicitTargets(targetPtgNode).Items())
1668 const auto kind = pointsToGraph.getNodeKind(calleePtgNode);
1671 const auto & calleeLambda = pointsToGraph.getLambdaForNode(calleePtgNode);
1672 const auto targetModRefSet =
1673 ModRefSummary_->getOrCreateSetForNode(calleeLambda, calleeLambda);
1681 if (pointsToGraph.isTargetingAllExternallyAvailable(targetPtgNode))
1689 auto blocklist =
Context_->SimpleAllocas;
1690 blocklist.DifferenceWith(reachableSimpleAllocas);
1692 Context_->CallBlocklists.push_back(std::move(blocklist));
1716 for (
auto target :
Context_->ModRefSetSimpleConstraints[workItem].Items())
1723 if (
auto blocklist =
Context_->ModRefSetBlocklists.find(target);
1724 blocklist !=
Context_->ModRefSetBlocklists.end())
1729 if (blocklist->second->Contains(memoryNode))
1732 changed |=
ModRefSummary_->addMemoryNodeToSet(target, memoryNode, mayMod);
1740 changed |=
ModRefSummary_->addMemoryNodeToSet(target, memoryNode, mayMod);
1757 for (
auto [index, blocklist] :
Context_->ModRefSetBlocklists)
1759 for (
auto [memoryNode, _] :
ModRefSummary_->getModRefSet(index).getModRefNodes())
1761 if (blocklist->Contains(memoryNode))
1771 const auto externModRefSet =
ModRefSummary_->getExternModRefSet();
1772 for (
auto [memoryNode, modRefEffect] :
1783 if (
ModRefSummary_->GetPointsToGraph().isExternallyAvailable(memoryNode))
1792 Context_->ReadOnlyMemoryNodes.insert(memoryNode);
1799 for (
auto & functions :
Context_->SccFunctions)
1801 for (
auto function : functions.Items())
1813 const auto & externModRefNodes =
1821 std::vector<PointsToGraph::NodeIndex> materializeExternallyAvailable;
1825 std::vector<std::pair<PointsToGraph::NodeIndex, ModRefEffect>> materializeFromCallToExtern;
1830 if (
Context_->ReadOnlyMemoryNodes.Contains(memoryNode))
1833 bool inserted = keepMemoryNodes.
insert(memoryNode);
1837 if (pointsToGraph.isExternallyAvailable(memoryNode))
1838 materializeExternallyAvailable.push_back(memoryNode);
1839 else if (
auto it = externModRefNodes.find(memoryNode); it != externModRefNodes.end())
1840 materializeFromCallToExtern.push_back(*it);
1847 const auto & allModRefSets =
ModRefSummary_->getAllSetsInFunction(lambda);
1848 for (
auto modRefSetIndex : allModRefSets)
1850 const auto & modRefSet =
ModRefSummary_->getModRefSet(modRefSetIndex);
1851 Context_->numModRefSetsMaterialized++;
1852 Context_->modRefSetSizeBeforeMaterialization += modRefSet.getModRefNodes().size();
1854 auto effectOnExternalNode = modRefSet.getImplicitModRefEffectForExternal(std::nullopt);
1861 for (
auto [memoryNode, modRefEffect] : modRefSet.getModRefNodes())
1868 markToKeep(memoryNode);
1874 for (
auto modRefSetIndex : allModRefSets)
1877 modRefSet.keepSubsetOfExplicitMemoryNodes(keepMemoryNodes);
1878 Context_->modRefSetSizeAfterFiltering += modRefSet.getModRefNodes().size();
1883 auto effectOnAllExternalNodes = modRefSet.getImplicitModRefEffectForExternal(1);
1884 auto effectOnLargeExternalNodes = modRefSet.getImplicitModRefEffectForExternal(std::nullopt);
1891 Context_->modRefSetSizeAfterMaterialization += modRefSet.getModRefNodes().size();
1897 if (effectOnLargeExternalNodes == effectOnAllExternalNodes)
1899 for (
auto memoryNode : materializeExternallyAvailable)
1901 modRefSet.addExplicitMemoryNode(memoryNode, effectOnLargeExternalNodes);
1907 for (
auto memoryNode : materializeExternallyAvailable)
1909 const auto memoryNodeSize = pointsToGraph.tryGetNodeSize(memoryNode);
1910 const auto modRefEffect = modRefSet.getImplicitModRefEffectForExternal(memoryNodeSize);
1912 modRefSet.addExplicitMemoryNode(memoryNode, modRefEffect);
1918 if (modRefSet.mayCallExternalFunction())
1920 Context_->numModRefSetsCallingExternalFunction++;
1921 for (
auto [memoryNode, modRefEffect] : materializeFromCallToExtern)
1923 modRefSet.addExplicitMemoryNode(memoryNode, modRefEffect);
1927 Context_->numModRefSetsWithEffectOnExternal++;
1928 Context_->modRefSetSizeAfterMaterialization += modRefSet.getModRefNodes().size();
1935 std::ostringstream ss;
1936 for (
size_t i = 0; i < summarizer.
Context_->SccFunctions.size(); i++)
1940 ss <<
"[" << std::endl;
1941 if (i == summarizer.
Context_->ExternalNodeSccIndex)
1943 ss <<
" " <<
"<external>" << std::endl;
1945 for (
auto function : summarizer.
Context_->SccFunctions[i].Items())
1947 ss <<
" " << function->DebugString() << std::endl;
1959 std::ostringstream ss;
1961 ss <<
"ExternModRefSet: "
1964 auto indent = [&](
size_t depth,
char c =
'-')
1966 for (
size_t i = 0; i < depth; i++)
1970 std::function<void(
const rvsdg::Node &,
size_t)> toRegionTree =
1987 for (
auto & region : structuralNode->Subregions())
1989 indent(depth + 1,
'-');
1990 ss <<
"RegionID: " << region.getRegionId() << std::endl;
1991 for (
auto & n : region.Nodes())
1992 toRegionTree(n, depth + 2);
1997 ss <<
"RootRegion:" << std::endl;
1999 toRegionTree(node, 0);
2004std::unique_ptr<ModRefSummary>
2014std::unique_ptr<ModRefSummary>
static jlm::util::StatisticsCollector statisticsCollector
static bool Contains(const jlm::llvm::InterProceduralGraphModule &module, const std::string &)
std::vector< rvsdg::Node * > nodes
static std::unique_ptr< CallTypeClassifier > ClassifyCall(const rvsdg::SimpleNode &callNode)
Classifies a call node.
static rvsdg::Input * Argument(const rvsdg::Node &node, const size_t n)
static size_t NumArguments(const rvsdg::Node &node) noexcept
static rvsdg::Input & addressInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & sourceInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & countInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & lengthInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & sourceInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & lengthInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
std::unordered_map< PointsToGraph::NodeIndex, ModRefEffect > modRefNodes_
const std::unordered_map< PointsToGraph::NodeIndex, ModRefEffect > & getModRefNodes() const
size_t numNodes() const noexcept
size_t numMemoryNodes() const noexcept
bool isExternallyAvailable(NodeIndex index) const
std::string getNodeDebugString(NodeIndex index, char separator=' ') const
std::optional< size_t > tryGetNodeSize(NodeIndex index) const noexcept
const util::HashSet< NodeIndex > & getExplicitTargets(NodeIndex index) const
NodeKind getNodeKind(NodeIndex index) const
bool isMemoryNode(NodeIndex index) const
static constexpr NodeIndex externalMemoryNode
bool markAsReferencingExternal(size_t minSize)
uint32_t refExternalOfSize_
ModRefEffect getImplicitModRefEffectForExternal(std::optional< size_t > size) const noexcept
bool markAsModifyingExternal(size_t minSize)
std::optional< size_t > getRefExternalMinSize() const
bool propagateFlags(const RegionAwareModRefSet &other)
bool addExplicitMemoryNode(PointsToGraph::NodeIndex memoryNode, ModRefEffect modRefEffect)
bool markAsCallingExternalFunction()
static constexpr uint32_t NoneSize
void keepSubsetOfExplicitMemoryNodes(const util::HashSet< PointsToGraph::NodeIndex > &filter)
std::optional< size_t > getModExternalMinSize() const
bool addMemoryNode(PointsToGraph::NodeIndex memoryNode, bool isExternallyAvailable, std::optional< size_t > memoryNodeSize, ModRefEffect modRefEffect)
uint32_t modExternalOfSize_
bool callsExternalFunction_
RegionAwareModRefSet()=default
bool mayCallExternalFunction() const
Region-aware mod/ref summarizer statistics.
void StopAnnotationStatistics()
static constexpr auto NumReadOnlyMemoryNodesDetectedLabel_
void StartAnnotationStatistics()
static constexpr auto NumModRefSetsCallingExternalFunctionLabel_
void stopReadOnlyMemoryDetectionStatistics(size_t numReadOnlyMemoryNodesDetected)
void stopModRefSetMaterializationStatistics(size_t numModRefSetsMaterialized, size_t modRefSetSizeBeforeMaterialization, size_t modRefSetSizeAfterFiltering, size_t numModRefSetsWithEffectOnExternal, size_t numModRefSetsCallingExternalFunction, size_t modRefSetSizeAfterMaterialization)
static constexpr auto NumCallGraphSccs_
void StartSolvingStatistics()
static constexpr auto NumSimpleAllocas_
~Statistics() override=default
static constexpr auto ModRefSetSizeBeforeMaterializationLabel_
static constexpr auto AllocasDeadInSccsTimer_
static std::unique_ptr< Statistics > Create(const rvsdg::RvsdgModule &rvsdgModule, const PointsToGraph &pointsToGraph)
static constexpr auto NumFunctionsCallingSetjmp_
static constexpr auto SimpleAllocasSetTimer_
void startReadOnlyMemoryDetectionStatistics()
void startCallGraphStatistics()
static constexpr auto CallGraphTimer_
void startModRefSetMaterializationStatistics()
void StartCreateSimpleAllocasSetStatistics()
static constexpr auto NumCallGraphSccsCanCallExternal_
static constexpr auto NonReentrantAllocaSetsTimer_
static constexpr auto ReadOnlyDetectionTimer_
static constexpr auto NumRvsdgRegionsLabel_
static constexpr auto NumNonReentrantAllocas_
static constexpr auto SolvingTimer_
Statistics(const rvsdg::RvsdgModule &rvsdgModule, const PointsToGraph &pointsToGraph)
void StopSolvingStatistics()
static constexpr auto NumModRefSetsMaterializedLabel_
void StartCreateNonReentrantAllocaSetsStatistics()
void StopCreateSimpleAllocasSetStatistics(uint64_t numSimpleAllocas)
static constexpr auto AnnotationTimer_
static constexpr auto ModRefSetSizeAfterFilteringLabel_
static constexpr auto ModRefSetSizeAfterMaterializationLabel_
void StopCreateNonReentrantAllocaSetsStatistics(size_t numNonReentrantAllocas)
static constexpr auto ModRefSetMaterializationTimer_
static constexpr auto NumModRefSetsWithEffectOnExternalLabel_
void stopCallGraphStatistics(size_t numSccs, size_t numFunctionsCallingSetjmp)
Region-aware mod/ref summarizer.
ModRefSetIndex AnnotateStore(const rvsdg::SimpleNode &storeNode, const rvsdg::LambdaNode &lambda)
ModRefSetIndex AnnotateMalloc(const rvsdg::SimpleNode &mallocNode, const rvsdg::LambdaNode &lambda)
void SolveModRefSetConstraintGraph()
static util::HashSet< PointsToGraph::NodeIndex > CreateSimpleAllocaSet(const PointsToGraph &pointsToGraph)
ModRefSetIndex AnnotateLoad(const rvsdg::SimpleNode &loadNode, const rvsdg::LambdaNode &lambda)
void addPointerOriginTargets(ModRefSetIndex modRefSetIndex, const rvsdg::Output &origin, std::optional< size_t > minTargetSize, ModRefEffect modRefEffect)
ModRefSetIndex AnnotateMemcpy(const rvsdg::SimpleNode &memcpyNode, const rvsdg::LambdaNode &lambda)
static std::unique_ptr< ModRefSummary > Create(const rvsdg::RvsdgModule &rvsdgModule, const PointsToGraph &pointsToGraph, util::StatisticsCollector &statisticsCollector)
void materializeSetsInFunction(const rvsdg::LambdaNode &lambda)
void AddModRefSetBlocklist(ModRefSetIndex index, const util::HashSet< PointsToGraph::NodeIndex > &blocklist)
~RegionAwareModRefSummarizer() noexcept override
std::optional< ModRefSetIndex > AnnotateSimpleNode(const rvsdg::SimpleNode &simpleNode, const rvsdg::LambdaNode &lambda)
ModRefSetIndex AnnotateAlloca(const rvsdg::SimpleNode &allocaNode, const rvsdg::LambdaNode &lambda)
std::unique_ptr< RegionAwareModRefSummary > ModRefSummary_
void AddModRefSimpleConstraint(ModRefSetIndex from, ModRefSetIndex to)
bool IsRecursionPossible(const rvsdg::LambdaNode &lambda) const
static std::string CallGraphSCCsToString(const RegionAwareModRefSummarizer &summarizer)
std::unique_ptr< ModRefSummary > SummarizeModRefs(const rvsdg::RvsdgModule &rvsdgModule, const PointsToGraph &pointsToGraph, util::StatisticsCollector &statisticsCollector) override
void createCallGraph(const rvsdg::RvsdgModule &rvsdgModule)
bool VerifyBlocklists() const
util::HashSet< PointsToGraph::NodeIndex > getSimpleAllocasReachableFromRegionArguments(const rvsdg::Region ®ion)
static std::string ToRegionTree(const rvsdg::Graph &rvsdg, const RegionAwareModRefSummary &modRefSummary)
void determineReadOnlyMemory()
util::HashSet< PointsToGraph::NodeIndex > getReachableSimpleAllocas(std::queue< PointsToGraph::NodeIndex > &nodes)
size_t CreateNonReentrantAllocaSets()
ModRefSetIndex AnnotateMemset(const rvsdg::SimpleNode &memsetNode, const rvsdg::LambdaNode &lambda)
util::HashSet< PointsToGraph::NodeIndex > getSimpleAllocasReachableFromCallArguments(const rvsdg::SimpleNode &call)
ModRefSetIndex AnnotateMemmove(const rvsdg::SimpleNode &memmoveNode, const rvsdg::LambdaNode &lambda)
std::unique_ptr< Context > Context_
void AnnotateRegion(const rvsdg::Region ®ion, ModRefSetIndex modRefSet, const rvsdg::LambdaNode &lambda)
void AnnotateFunction(const rvsdg::LambdaNode &lambda)
ModRefSetIndex AnnotateFree(const rvsdg::SimpleNode &freeNode, const rvsdg::LambdaNode &lambda)
ModRefSetIndex AnnotateStructuralNode(const rvsdg::StructuralNode &structuralNode, const rvsdg::LambdaNode &lambda)
ModRefSetIndex AnnotateCall(const rvsdg::SimpleNode &callNode, const rvsdg::LambdaNode &lambda)
Mod/Ref summary of region-aware mod/ref summarizer.
const std::vector< ModRefSetIndex > & getAllSetsInFunction(const rvsdg::LambdaNode &lambdaNode)
std::string getModRefSetDebugString(ModRefSetIndex index) const
ModRefSetIndex getOrCreateSetForNode(const rvsdg::Node &node, const rvsdg::LambdaNode &lambdaNode)
static std::unique_ptr< RegionAwareModRefSummary > Create(const PointsToGraph &pointsToGraph)
RegionAwareModRefSummary & operator=(const RegionAwareModRefSummary &)=delete
bool markSetAsModifyingExternal(ModRefSetIndex index, size_t minSize)
ModRefSetIndex externModRefSet_
const RegionAwareModRefSet & getModRefSet(ModRefSetIndex index) const
const ModRefSet & GetLambdaEntryModRef(const rvsdg::LambdaNode &lambda) const override
bool hasSetForNode(const rvsdg::Node &node) const
bool addMemoryNodeToSet(ModRefSetIndex index, PointsToGraph::NodeIndex ptgNode, ModRefEffect modRefEffect)
const ModRefSet & GetSimpleNodeModRef(const rvsdg::SimpleNode &node) const override
RegionAwareModRefSummary(const PointsToGraph &pointsToGraph)
bool markSetAsReferencingExternal(ModRefSetIndex index, size_t minSize)
bool markSetAsCallingExternalFunction(ModRefSetIndex index)
RegionAwareModRefSummary(const RegionAwareModRefSummary &)=delete
std::vector< RegionAwareModRefSet > modRefSets_
std::unordered_map< const rvsdg::Node *, ModRefSetIndex > nodeMap_
RegionAwareModRefSet & getModRefSet(ModRefSetIndex index)
const ModRefSet & GetGammaExitModRef(const rvsdg::GammaNode &gamma) const override
const PointsToGraph & GetPointsToGraph() const noexcept override
std::unordered_map< const rvsdg::LambdaNode *, std::vector< ModRefSetIndex > > modRefSetsInFunction_
ModRefSetIndex createModRefSet()
ModRefSetIndex getExternModRefSet() const noexcept
const ModRefSet & GetGammaEntryModRef(const rvsdg::GammaNode &gamma) const override
const ModRefSet & GetLambdaExitModRef(const rvsdg::LambdaNode &lambda) const override
ModRefSetIndex getSetForNode(const rvsdg::Node &node) const
size_t NumModRefSets() const noexcept
const PointsToGraph & pointsToGraph_
const ModRefSet & GetThetaModRef(const rvsdg::ThetaNode &theta) const override
bool addExplicitMemoryNodeToSet(ModRefSetIndex index, PointsToGraph::NodeIndex ptgNode, ModRefEffect modRefEffect)
Conditional operator / pattern matching.
Region & GetRootRegion() const noexcept
Id GetNodeId() const noexcept
virtual std::string DebugString() const =0
Represent acyclic RVSDG subgraphs.
RegionArgumentRange Arguments() noexcept
static size_t NumRegions(const rvsdg::Region ®ion) noexcept
NodeRange Nodes() noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
SubregionIteratorRange Subregions()
bool insert(ItemType item)
bool Contains(const ItemType &item) const noexcept
bool Remove(ItemType item)
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
util::Timer & GetTimer(const std::string &name)
util::Timer & AddTimer(std::string name)
void AddMeasurement(std::string name, T value)
void PushWorkItem(T item) override
bool HasMoreWorkItems() const noexcept override
#define JLM_UNREACHABLE(msg)
static const bool ENABLE_READ_ONLY_DETECTION
static const bool ENABLE_CALL_SIMPLE_ALLOCA_BLOCKING
static std::vector< const rvsdg::LambdaNode * > CollectLambdaNodes(const rvsdg::RvsdgModule &rvsdgModule)
bool IsPointerCompatible(const rvsdg::Output &value)
bool isEffectSubset(ModRefEffect subset, ModRefEffect superset)
bool mayEffectModify(ModRefEffect effect)
bool mayEffectReference(ModRefEffect effect)
static const bool ENABLE_CONSTANT_MEMORY_BLOCKING
static const bool ENABLE_OPERATION_SIZE_BLOCKING
static const bool ENABLE_NON_REENTRANT_ALLOCA_BLOCKLIST
size_t GetTypeStoreSize(const rvsdg::Type &type)
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
void MatchType(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
size_t numModRefSetsWithEffectOnExternal
size_t numModRefSetsCallingExternalFunction
size_t ExternalNodeSccIndex
size_t modRefSetSizeBeforeMaterialization
std::vector< util::HashSet< const rvsdg::LambdaNode * > > SccFunctions
size_t modRefSetSizeAfterFiltering
Context(const PointsToGraph &ptg)
util::HashSet< PointsToGraph::NodeIndex > SimpleAllocas
std::unordered_map< const rvsdg::Node *, util::HashSet< PointsToGraph::NodeIndex > > NonReentrantAllocas
util::HashSet< const rvsdg::LambdaNode * > FunctionsCallingSetjmp
std::unordered_map< const rvsdg::LambdaNode *, size_t > FunctionToSccIndex
size_t modRefSetSizeAfterMaterialization
std::vector< util::HashSet< size_t > > SccCallTargets
std::deque< util::HashSet< PointsToGraph::NodeIndex > > CallBlocklists
size_t numModRefSetsMaterialized
const PointsToGraph & pointsToGraph
std::vector< util::HashSet< ModRefSetIndex > > ModRefSetSimpleConstraints
util::HashSet< PointsToGraph::NodeIndex > ReadOnlyMemoryNodes
std::unordered_map< ModRefSetIndex, const util::HashSet< PointsToGraph::NodeIndex > * > ModRefSetBlocklists