73 throw std::logic_error(
"Node is not an alloca operation");
75 auto [it, added] =
allocaMap_.try_emplace(&allocaNode, 0);
77 throw std::logic_error(
"Alloca node already exists in the graph.");
80 const auto getMemorySize = [](
const rvsdg::Node & allocaNode) -> std::optional<size_t>
82 const auto allocaOp = util::assertedCast<const AllocaOperation>(
87 if (elementCount.has_value() && *elementCount >= 0)
96 getMemorySize(allocaNode),
103 auto [it, added] =
deltaMap_.try_emplace(&deltaNode, 0);
105 throw std::logic_error(
"Delta node already exists in the graph.");
117 auto [it, added] =
importMap_.try_emplace(&
import, 0);
119 throw std::logic_error(
"Import node already exists in the graph.");
123 if (
const auto graphImport =
dynamic_cast<const LlvmGraphImport *
>(&
import))
124 return graphImport->isConstant();
128 const auto getMemorySize = [](
const rvsdg::GraphImport &
import) -> std::optional<size_t>
130 if (
const auto graphImport =
dynamic_cast<const LlvmGraphImport *
>(&
import))
148 getMemorySize(
import),
155 auto [it, added] =
lambdaMap_.try_emplace(&lambdaNode, 0);
157 throw std::logic_error(
"Lambda node already exists in the graph.");
168 throw std::logic_error(
"Node is not an alloca operation");
170 auto [it, added] =
mallocMap_.try_emplace(&mallocNode, 0);
172 throw std::logic_error(
"Malloc node already exists in the graph.");
174 const auto tryGetMemorySize = [](
const rvsdg::Node & mallocNode) -> std::optional<size_t>
180 if (size.has_value() && *size >= 0)
190 tryGetMemorySize(mallocNode),
208 throw std::logic_error(
"Node is not a register node");
210 const auto [_, added] =
registerMap_.emplace(&output, nodeIndex);
212 throw std::logic_error(
"Register is already mapped in the graph.");
222 nodeData_[index].isTargetingAllExternallyAvailable =
true;
245 std::pair<size_t, size_t>
248 size_t numExplicitEdges = 0;
249 size_t numImplicitEdges = 0;
250 size_t numDoubledUpEdges = 0;
265 return std::make_pair(numExplicitEdges, numExplicitEdges + numImplicitEdges - numDoubledUpEdges);
271 std::ostringstream ss;
272 ss <<
"(PtG#" << std::setfill(
'0') << std::setw(3) << index << std::setw(0) <<
" ";
298 throw std::logic_error(
"Unknown PtG node kind");
303 ss << seperator <<
"(ExtAv)";
307 ss << seperator <<
"(TgtAllExtAv)";
312 ss << seperator <<
"(" << size.value() <<
" bytes)";
316 ss << seperator <<
"(const)";
329 auto getCorrespondingMemoryNode = [](
NodeIndex node,
333 const auto kind = original.getNodeKind(node);
336 const auto & alloca = original.getAllocaForNode(node);
337 if (!other.hasNodeForAlloca(alloca))
339 return other.getNodeForAlloca(alloca);
343 const auto & delta = original.getDeltaForNode(node);
344 if (!other.hasNodeForDelta(delta))
346 return other.getNodeForDelta(delta);
350 const auto & argument = original.getImportForNode(node);
351 if (!other.hasNodeForImport(argument))
353 return other.getNodeForImport(argument);
357 const auto & lambda = original.getLambdaForNode(node);
358 if (!other.hasNodeForLambda(lambda))
360 return other.getNodeForLambda(lambda);
364 const auto & malloc = original.getMallocForNode(node);
365 if (!other.hasNodeForMalloc(malloc))
367 return other.getNodeForMalloc(malloc);
371 return other.getExternalMemoryNode();
374 throw std::logic_error(
"Unknown type of memory node");
379 auto isNodeSuperset = [&](
const PointsToGraph & supersetGraph,
385 if (subsetGraph.isExternallyAvailable(subsetNode)
389 if (subsetGraph.isTargetingAllExternallyAvailable(subsetNode)
394 for (
auto subsetTarget : subsetGraph.getExplicitTargets(subsetNode).Items())
397 auto correspondingTarget =
398 getCorrespondingMemoryNode(subsetTarget, subsetGraph, supersetGraph);
399 if (!correspondingTarget.has_value())
421 auto hasSuperOfMemoryNode = [&](
NodeIndex subsetNode)
423 auto thisNode = getCorrespondingMemoryNode(subsetNode, subgraph, *
this);
424 if (!thisNode.has_value())
427 return isNodeSuperset(*
this, *thisNode, subgraph, subsetNode);
433 if (!hasSuperOfMemoryNode(node))
438 if (!hasSuperOfMemoryNode(node))
443 if (!hasSuperOfMemoryNode(node))
448 if (!hasSuperOfMemoryNode(node))
453 if (!hasSuperOfMemoryNode(node))
460 for (
auto [rvsdgOutput, subNode] : subgraph.
registerMap_)
466 if (!isNodeSuperset(*
this, supersetRegisterNode, subgraph, subNode))
476 bool externallyAvailable,
478 std::optional<size_t> memorySize,
483 nodeData_.emplace_back(
NodeData(kind, externallyAvailable,
false, isConstant, memorySize));
487 if (externallyAvailable)
496 const auto [explicitEdges, totalEdges] = pointsToGraph.
numEdges();
501 util::strfmt(
"Explicit edges: ", explicitEdges,
", total edges: ", totalEdges));
503 std::vector<util::graph::Node *> nodes;
504 nodes.resize(pointsToGraph.
numNodes());
508 auto & node = graph.CreateNode();
516 node.SetShape(
"box");
517 node.SetAttributeObject(
"rvsdgObject", pointsToGraph.
nodeObjects_[ptgNode]);
522 node.SetShape(
"oval");
525 nodes[ptgNode] = &node;
529 std::unordered_map<NodeIndex, size_t> outputCount;
530 for (
const auto & [rvsdgOutput, ptgNode] : pointsToGraph.
registerMap_)
532 const auto count = outputCount[ptgNode]++;
533 nodes[ptgNode]->SetAttributeObject(
util::strfmt(
"output", count), rvsdgOutput);
541 graph.CreateEdge(*nodes[ptgNode], *nodes[target],
true);
551 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
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
static constexpr NodeIndex externalMemoryNode
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)