53 const size_t numAggregateAllocaNodes,
54 const size_t numAggregateStructAllocaNodes,
55 const size_t numSplitableTypeAggregateAllocaNodes,
56 const size_t numSplitAggregateAllocaNodes)
63 numSplitableTypeAggregateAllocaNodes);
67 static std::unique_ptr<Statistics>
70 return std::make_unique<Statistics>(std::move(filePath));
103 const auto structType =
dynamic_cast<const StructType *
>(&type);
107 for (
const auto & elementType : structType->elementTypes())
118std::optional<AggregateAllocaSplitting::AllocaTraceInfo>
121 [[maybe_unused]]
auto allocaOperation =
129 if (!countOpt.has_value() || countOpt.value() != 1)
139 std::deque<rvsdg::Output *> toVisit{ &address };
144 toVisit.push_back(&output);
148 auto removeFromVisitSet = [&]()
150 const auto output = toVisit.front();
157 const auto currentOutput = removeFromVisitSet();
159 for (
auto & user : currentOutput->Users())
176 auto & gammaOutput = gammaNode.mapBranchResultToOutput(user);
177 addToVisitSet(gammaOutput);
182 const auto loopVar = thetaNode.MapPostLoopVar(user);
183 addToVisitSet(*loopVar.pre);
184 addToVisitSet(*loopVar.output);
193 throw std::logic_error(util::strfmt(
194 "Unhandled owner region node type: ",
195 userRegion->node()->DebugString()));
206 auto roleVar = gammaNode.
MapInput(user);
207 if (
auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
209 for (
auto argument : entryVar->branchArgument)
211 addToVisitSet(*argument);
216 throw std::logic_error(
util::strfmt(
"Unhandled role variable."));
223 const auto loopVar = thetaNode.MapInputLoopVar(user);
224 addToVisitSet(*loopVar.pre);
229 auto & operation = simpleNode.GetOperation();
246 throw std::logic_error(
247 util::strfmt(
"Unhandled node type: ", userNode->DebugString()));
254 throw std::logic_error(
"Unhandled owner type");
268 return std::make_optional(allocaTraceInfo);
274 [[maybe_unused]]
auto gepOperation =
276 auto & address = *gepNode.
output(0);
278 bool hasOnlyLoadsAndStores =
true;
281 std::deque<rvsdg::Output *> toVisit{ &address };
286 toVisit.push_back(&output);
290 auto removeFromVisitSet = [&]()
292 const auto output = toVisit.front();
297 while (!toVisit.empty() && hasOnlyLoadsAndStores)
299 const auto currentOutput = removeFromVisitSet();
300 for (
auto & user : currentOutput->Users())
302 if (!hasOnlyLoadsAndStores)
317 auto & gammaOutput = gammaNode.mapBranchResultToOutput(user);
318 addToVisitSet(gammaOutput);
323 const auto loopVar = thetaNode.MapPostLoopVar(user);
324 addToVisitSet(*loopVar.pre);
325 addToVisitSet(*loopVar.output);
334 throw std::logic_error(util::strfmt(
335 "Unhandled owner region node type: ",
336 userRegion->node()->DebugString()));
347 auto roleVar = gammaNode.
MapInput(user);
348 if (
auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
350 for (
auto argument : entryVar->branchArgument)
352 addToVisitSet(*argument);
357 throw std::logic_error(
util::strfmt(
"Unhandled role variable."));
364 const auto loopVar = thetaNode.MapInputLoopVar(user);
365 addToVisitSet(*loopVar.pre);
370 auto & operation = simpleNode.GetOperation();
386 addToVisitSet(*simpleNode.output(0));
396 throw std::logic_error(
397 util::strfmt(
"Unhandled node type: ", userNode->DebugString()));
404 throw std::logic_error(
"Unhandled owner type");
409 return hasOnlyLoadsAndStores;
412std::vector<AggregateAllocaSplitting::AllocaTraceInfo>
415 std::function<void(
rvsdg::Region &, std::vector<AllocaTraceInfo> &)> findAllocaNodes =
416 [&](
rvsdg::Region & region, std::vector<AllocaTraceInfo> & traceInfo)
418 for (
auto & node : region.
Nodes())
420 MatchTypeWithDefault(
424 for (
auto & subregion : gammaNode.
Subregions())
425 findAllocaNodes(subregion, traceInfo);
429 findAllocaNodes(*thetaNode.subregion(), traceInfo);
433 findAllocaNodes(*lambdaNode.subregion(), traceInfo);
437 findAllocaNodes(*phiNode.subregion(), traceInfo);
445 const auto allocaOperation =
447 if (!allocaOperation)
451 if (is<StructType>(allocaType))
453 context_->numAggregateStructAllocaNodes++;
454 context_->numAggregateAllocaNodes++;
458 context_->numAggregateAllocaNodes++;
463 context_->numSplitableTypeAggregateAllocaNodes++;
464 if (
auto allocaTraceInfo =
isSplitable(simpleNode))
466 traceInfo.emplace_back(*allocaTraceInfo);
472 throw std::logic_error(
"Unhandled node type.");
477 std::vector<AllocaTraceInfo> traceInfo;
478 findAllocaNodes(region, traceInfo);
487 std::size_t hash = 0;
488 for (
auto & index : v)
501 const auto allocaOperation =
502 util::assertedCast<const AllocaOperation>(&allocaNode.
GetOperation());
503 auto & allocaType = *util::assertedCast<const StructType>(allocaOperation->allocatedType().get());
505 const auto alignment = allocaOperation->alignment();
508 createAllocaNodes = [&](
const StructType & structType,
510 std::vector<uint64_t> & indices)
513 for (
const auto & elementType : structType.
elementTypes())
515 indices.push_back(index++);
516 if (
auto structType = std::dynamic_pointer_cast<const StructType>(elementType))
518 createAllocaNodes(*structType, allocaNodes, indices);
522 auto & elementAlloca =
525 allocaNodes[indices] = &elementAlloca;
533 std::vector<uint64_t> indices(1, 0);
534 createAllocaNodes(allocaType, allocaNodes, indices);
541 auto & allocaNode = *allocaTraceInfo.
allocaNode;
542 const auto allocaOperation =
dynamic_cast<const AllocaOperation *
>(&allocaNode.GetOperation());
545 std::vector<rvsdg::Output *> allocaMemoryStates;
547 for (
auto [_, elementAllocaNode] : elementAllocaMap)
560 allocaConsumer->GetOperation(),
563 JLM_ASSERT(GetElementPtrOperation::numIndices(*allocaConsumer) >= 2);
564 auto & consumerRegion = *allocaConsumer->region();
565 const auto gepConstant =
566 GetElementPtrOperation::tryGetAsConstant(*allocaConsumer).value();
567 JLM_ASSERT(gepConstant.indices[0] == 0);
569 auto elementAlloca = elementAllocaMap.at(gepConstant.indices);
571 auto & routedAddress = rvsdg::RouteToRegion(
572 AllocaOperation::getPointerOutput(*elementAlloca),
574 allocaConsumer->output(0)->divert_users(&routedAddress);
578 throw std::logic_error(
579 util::strfmt(
"Unhandled node type: ", allocaConsumer->DebugString()));
588 for (
const auto & allocaTraceInfo : traceInfo)
591 context_->numSplitAggregateAllocaNodes++;
603 context_ = std::make_unique<Context>();
610 context_->numAggregateStructAllocaNodes,
611 context_->numSplitableTypeAggregateAllocaNodes,
612 context_->numSplitAggregateAllocaNodes);
static jlm::util::StatisticsCollector statisticsCollector
static std::unique_ptr< Statistics > create(util::FilePath filePath)
const char * numSplitAggregateAllocaNodesLabel_
~Statistics() noexcept override=default
void stop(const size_t numAggregateAllocaNodes, const size_t numAggregateStructAllocaNodes, const size_t numSplitableTypeAggregateAllocaNodes, const size_t numSplitAggregateAllocaNodes)
const char * numAggregateAllocaNodesLabel_
const char * numSplitableTypeAggregateAllocaNodesLabel_
const char * numAggregateStructAllocaNodesLabel_
const char * aggregateAllocaSplittingTimerLabel_
Aggregate Alloca Splitting Transformation.
std::unique_ptr< Context > context_
static bool checkGetElementPtrUsers(const rvsdg::SimpleNode &gepNode)
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static void splitAllocaNode(const AllocaTraceInfo &allocaTraceInfo)
void splitAllocaNodes(rvsdg::RvsdgModule &rvsdgModule)
static bool isSplitableType(const rvsdg::Type &type)
static std::optional< AllocaTraceInfo > isSplitable(rvsdg::SimpleNode &allocaNode)
~AggregateAllocaSplitting() noexcept override
std::vector< AllocaTraceInfo > findSplitableAllocaNodes(rvsdg::Region ®ion) const
static rvsdg::SimpleNode & createNode(std::shared_ptr< const rvsdg::Type > allocatedType, rvsdg::Output &count, const size_t alignment)
static rvsdg::Output & getPointerOutput(rvsdg::Node &node)
static rvsdg::Output & getMemoryStateOutput(rvsdg::Node &node)
const std::shared_ptr< const rvsdg::Type > & allocatedType() const noexcept
static rvsdg::Input & getCountInput(rvsdg::Node &node)
static std::optional< Constant > tryGetAsConstant(const rvsdg::SimpleNode &gepNode)
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
ElementTypeConstRange elementTypes() const noexcept
Conditional operator / pattern matching.
std::variant< MatchVar, EntryVar > MapInput(const rvsdg::Input &input) const
Maps gamma input to its role (match variable or entry variable).
Region & GetRootRegion() const noexcept
void divert_users(jlm::rvsdg::Output *new_origin)
A phi node represents the fixpoint of mutually recursive definitions.
Represent acyclic RVSDG subgraphs.
NodeRange Nodes() noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeOutput * output(size_t index) const noexcept
SubregionIteratorRange Subregions()
bool insert(ItemType item)
bool Contains(const ItemType &item) const noexcept
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)
Global memory state passed between functions.
static VectorNodeHashMap createElementAllocaNodes(rvsdg::SimpleNode &allocaNode)
std::unordered_map< std::vector< uint64_t >, rvsdg::Node *, VectorHash > VectorNodeHashMap
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
bool IsAggregateType(const jlm::rvsdg::Type &type)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
Region * TryGetOwnerRegion(const rvsdg::Input &input) noexcept
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
static std::string strfmt(Args... args)
std::size_t CombineHashes(std::size_t hash, Args... args)
std::vector< rvsdg::SimpleNode * > allocaConsumers
rvsdg::SimpleNode * allocaNode
AllocaTraceInfo(rvsdg::SimpleNode &allocaNode)
size_t numSplitableTypeAggregateAllocaNodes
size_t numAggregateAllocaNodes
size_t numSplitAggregateAllocaNodes
size_t numAggregateStructAllocaNodes
size_t operator()(const std::vector< uint64_t > &v) const