70 throw std::logic_error(
"Node is not an alloca operation");
72 auto [it, added] =
allocaMap_.try_emplace(&allocaNode, 0);
74 throw std::logic_error(
"Alloca node already exists in the graph.");
77 const auto getMemorySize = [](
const rvsdg::Node & allocaNode) -> std::optional<size_t>
79 const auto allocaOp = util::assertedCast<const AllocaOperation>(
84 if (elementCount.has_value() && *elementCount >= 0)
93 getMemorySize(allocaNode),
100 auto [it, added] =
deltaMap_.try_emplace(&deltaNode, 0);
102 throw std::logic_error(
"Delta node already exists in the graph.");
114 auto [it, added] =
importMap_.try_emplace(&
import, 0);
116 throw std::logic_error(
"Import node already exists in the graph.");
120 if (
const auto graphImport =
dynamic_cast<const LlvmGraphImport *
>(&
import))
121 return graphImport->isConstant();
125 const auto getMemorySize = [](
const rvsdg::GraphImport &
import) -> std::optional<size_t>
127 if (
const auto graphImport =
dynamic_cast<const LlvmGraphImport *
>(&
import))
145 getMemorySize(
import),
152 auto [it, added] =
lambdaMap_.try_emplace(&lambdaNode, 0);
154 throw std::logic_error(
"Lambda node already exists in the graph.");
165 throw std::logic_error(
"Node is not an alloca operation");
167 auto [it, added] =
mallocMap_.try_emplace(&mallocNode, 0);
169 throw std::logic_error(
"Malloc node already exists in the graph.");
171 const auto tryGetMemorySize = [](
const rvsdg::Node & mallocNode) -> std::optional<size_t>
177 if (size.has_value() && *size >= 0)
187 tryGetMemorySize(mallocNode),
205 throw std::logic_error(
"Node is not a register node");
207 const auto [_, added] =
registerMap_.emplace(&output, nodeIndex);
209 throw std::logic_error(
"Register is already mapped in the graph.");
219 nodeData_[index].isTargetingAllExternallyAvailable =
true;
242 std::pair<size_t, size_t>
245 size_t numExplicitEdges = 0;
246 size_t numImplicitEdges = 0;
247 size_t numDoubledUpEdges = 0;
262 return std::make_pair(numExplicitEdges, numExplicitEdges + numImplicitEdges - numDoubledUpEdges);
268 std::ostringstream ss;
269 ss <<
"(PtG#" << std::setfill(
'0') << std::setw(3) << index << std::setw(0) <<
" ";
295 throw std::logic_error(
"Unknown PtG node kind");
300 ss << seperator <<
"(ExtAv)";
304 ss << seperator <<
"(TgtAllExtAv)";
309 ss << seperator <<
"(" << size.value() <<
" bytes)";
313 ss << seperator <<
"(const)";
326 auto getCorrespondingMemoryNode = [](
NodeIndex node,
330 const auto kind = original.getNodeKind(node);
333 const auto & alloca = original.getAllocaForNode(node);
334 if (!other.hasNodeForAlloca(alloca))
336 return other.getNodeForAlloca(alloca);
340 const auto & delta = original.getDeltaForNode(node);
341 if (!other.hasNodeForDelta(delta))
343 return other.getNodeForDelta(delta);
347 const auto & argument = original.getImportForNode(node);
348 if (!other.hasNodeForImport(argument))
350 return other.getNodeForImport(argument);
354 const auto & lambda = original.getLambdaForNode(node);
355 if (!other.hasNodeForLambda(lambda))
357 return other.getNodeForLambda(lambda);
361 const auto & malloc = original.getMallocForNode(node);
362 if (!other.hasNodeForMalloc(malloc))
364 return other.getNodeForMalloc(malloc);
368 return other.getExternalMemoryNode();
371 throw std::logic_error(
"Unknown type of memory node");
376 auto isNodeSuperset = [&](
const PointsToGraph & supersetGraph,
382 if (subsetGraph.isExternallyAvailable(subsetNode)
386 if (subsetGraph.isTargetingAllExternallyAvailable(subsetNode)
391 for (
auto subsetTarget : subsetGraph.getExplicitTargets(subsetNode).Items())
394 auto correspondingTarget =
395 getCorrespondingMemoryNode(subsetTarget, subsetGraph, supersetGraph);
396 if (!correspondingTarget.has_value())
418 auto hasSuperOfMemoryNode = [&](
NodeIndex subsetNode)
420 auto thisNode = getCorrespondingMemoryNode(subsetNode, subgraph, *
this);
421 if (!thisNode.has_value())
424 return isNodeSuperset(*
this, *thisNode, subgraph, subsetNode);
430 if (!hasSuperOfMemoryNode(node))
435 if (!hasSuperOfMemoryNode(node))
440 if (!hasSuperOfMemoryNode(node))
445 if (!hasSuperOfMemoryNode(node))
450 if (!hasSuperOfMemoryNode(node))
457 for (
auto [rvsdgOutput, subNode] : subgraph.
registerMap_)
463 if (!isNodeSuperset(*
this, supersetRegisterNode, subgraph, subNode))
473 bool externallyAvailable,
475 std::optional<size_t> memorySize,
480 nodeData_.emplace_back(
NodeData(kind, externallyAvailable,
false, isConstant, memorySize));
484 if (externallyAvailable)
493 const auto [explicitEdges, totalEdges] = pointsToGraph.
numEdges();
498 util::strfmt(
"Explicit edges: ", explicitEdges,
", total edges: ", totalEdges));
500 std::vector<util::graph::Node *> nodes;
501 nodes.resize(pointsToGraph.
numNodes());
505 auto & node = graph.CreateNode();
513 node.SetShape(
"box");
514 node.SetAttributeObject(
"rvsdgObject", pointsToGraph.
nodeObjects_[ptgNode]);
519 node.SetShape(
"oval");
522 nodes[ptgNode] = &node;
526 std::unordered_map<NodeIndex, size_t> outputCount;
527 for (
const auto & [rvsdgOutput, ptgNode] : pointsToGraph.
registerMap_)
529 const auto count = outputCount[ptgNode]++;
530 nodes[ptgNode]->SetAttributeObject(
util::strfmt(
"output", count), rvsdgOutput);
538 graph.CreateEdge(*nodes[ptgNode], *nodes[target],
true);
548 std::ostringstream ss;
static rvsdg::Input & sizeInput(const rvsdg::Node &node)
std::optional< size_t > tryGetNodeSize(NodeIndex index) const noexcept
RegisterNodeRange registerNodes() const noexcept
util::MapValueIterator< const NodeIndex, LambdaNodeMap::const_iterator > LambdaNodeIterator
const rvsdg::SimpleNode & getMallocForNode(NodeIndex index) const
static void dumpGraph(util::graph::Writer &graphWriter, const PointsToGraph &pointsToGraph)
size_t numNodes() const noexcept
const rvsdg::SimpleNode & getAllocaForNode(NodeIndex index) const
const rvsdg::GraphImport & getImportForNode(NodeIndex index) const
const util::HashSet< NodeIndex > & getExplicitTargets(NodeIndex index) const
NodeIndex getNodeForRegister(const rvsdg::Output &output) const
NodeIndex addNodeForMalloc(const rvsdg::SimpleNode &mallocNode, bool externallyAvailable)
util::MapValueIterator< const NodeIndex, DeltaNodeMap::const_iterator > DeltaNodeIterator
bool isExternallyAvailable(NodeIndex index) const
NodeIndex addNodeForRegisters()
NodeIndex addNodeForImport(const rvsdg::GraphImport &argument, bool externallyAvailable)
size_t numNodesTargetingAllExternallyAvailable_
std::string getNodeDebugString(NodeIndex index, char separator=' ') const
NodeIndex addNode(NodeKind kind, bool externallyAvailable, bool isConstant, std::optional< size_t > memorySize, const void *object)
AllocaNodeRange allocaNodes() const noexcept
NodeIndex externalMemoryNode_
bool isTargetingAllExternallyAvailable(NodeIndex index) const
std::vector< NodeData > nodeData_
NodeIndex getExternalMemoryNode() const noexcept
const rvsdg::LambdaNode & getLambdaForNode(NodeIndex index) const
NodeIndex addNodeForAlloca(const rvsdg::SimpleNode &allocaNode, bool externallyAvailable)
void mapRegisterToNode(const rvsdg::Output &output, NodeIndex nodeIndex)
NodeIndex addNodeForLambda(const rvsdg::LambdaNode &lambdaNode, bool externallyAvailable)
NodeIndex addNodeForDelta(const rvsdg::DeltaNode &deltaNode, bool externallyAvailable)
bool isSupergraphOf(const PointsToGraph &subgraph) const
bool isNodeConstant(NodeIndex index) const noexcept
LambdaNodeRange lambdaNodes() const noexcept
std::vector< const void * > nodeObjects_
DeltaNodeRange deltaNodes() const noexcept
bool addTarget(NodeIndex source, NodeIndex target)
void markAsTargetsAllExternallyAvailable(NodeIndex index)
util::MapValueIterator< const NodeIndex, AllocaNodeMap::const_iterator > AllocaNodeIterator
bool isRegisterNode(NodeIndex index) const
std::vector< NodeIndex > registerNodes_
static std::string dumpDot(const PointsToGraph &pointsToGraph)
NodeKind getNodeKind(NodeIndex index) const
bool isMemoryNode(NodeIndex index) const
bool hasNodeForRegister(const rvsdg::Output &output) const
const rvsdg::DeltaNode & getDeltaForNode(NodeIndex index) const
std::vector< util::HashSet< NodeIndex > > nodeExplicitTargets_
std::pair< size_t, size_t > numEdges() const noexcept
RegisterNodeMap registerMap_
util::MapValueIterator< const NodeIndex, MallocNodeMap::const_iterator > MallocNodeIterator
MallocNodeRange mallocNodes() const noexcept
util::MapValueIterator< const NodeIndex, ImportNodeMap::const_iterator > ImportNodeIterator
ImportNodeRange importNodes() const noexcept
std::vector< NodeIndex > externallyAvailableNodes_
const DeltaOperation & GetOperation() const noexcept override
bool constant() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
std::string debug_string() const override
const SimpleOperation & GetOperation() const noexcept override
std::string DebugString() const override
NodeInput * input(size_t index) const noexcept
std::string DebugString() const override
void SetLabel(std::string label)
void outputAllGraphs(std::ostream &out, OutputFormat format)
size_t GetTypeAllocSize(const rvsdg::Type &type)
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
static std::string strfmt(Args... args)