53 static std::unique_ptr<Statistics>
56 return std::make_unique<Statistics>(sourceFile);
86 static std::unique_ptr<Context>
89 return std::make_unique<Context>(lambdaNode);
94 std::unordered_map<const rvsdg::Node *, rvsdg::Region *>
TargetRegion_{};
106 if (!is<MemoryStateType>(loopVar.
output->
Type()))
117 if (userNode ==
nullptr || originNode ==
nullptr || userNode != originNode)
135 if (is<IOStateType>(output.
Type()))
141 const auto roleVar = gammaNode->MapBranchArgument(output);
142 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
153 const auto loopVar = thetaNode->MapPreLoopVar(output);
170 return context_->getTargetRegion(*gammaNode);
176 return context_->getTargetRegion(*thetaNode);
182 return context_->getTargetRegion(*node);
185 throw std::logic_error(
"Unhandled output type!");
191 for (
auto & input : node.
Inputs())
218 auto currentRegion = node.
region();
226 currentRegion = currentRegion->
node()->
region();
227 }
while (currentRegion != &targetRegion);
229 return *currentRegion;
242 const auto outputType = node.
output(0)->
Type();
243 if (is<rvsdg::ControlType>(outputType))
247 return context_->getLambdaSubregion();
253 for (
auto & input : node.
Inputs())
256 if (&targetRegion == node.
region())
264 if (greatestCommonTargetRegion
265 && greatestCommonTargetRegion->
getDepth() >= targetRegion.getDepth())
267 greatestCommonTargetRegion = &targetRegion;
270 greatestCommonTargetRegion = &
limitTargetRegion(node, *greatestCommonTargetRegion);
274 return *greatestCommonTargetRegion;
287 context_->addTargetRegion(structuralNode, *structuralNode.
region());
290 for (
auto & subregion : structuralNode.
Subregions())
298 context_->addTargetRegion(*node, targetRegion);
302 throw std::logic_error(
"Unhandled node type!");
310 if (input.
region() == &targetRegion)
313 const auto & operand = *input.
origin();
318 const auto roleVar = gammaNode->MapBranchArgument(operand);
319 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
328 const auto loopVar = thetaNode->MapPreLoopVar(operand);
335 if (is<LoadNonVolatileOperation>(simpleNode->GetOperation()))
342 throw std::logic_error(
"Unhandled output type!");
345std::vector<rvsdg::Input *>
348 std::vector<rvsdg::Input *> users;
349 for (
auto & input : node.
Inputs())
352 users.push_back(&user);
367 simpleNode->GetOperation(),
370 return &LoadOperation::MapMemoryStateOutputToInput(output);
374 return &StoreOperation::MapMemoryStateOutputToInput(output);
378 if (is<IOStateType>(output.Type()))
380 return &CallOperation::mapIOStateOutputToInput(output);
383 if (is<MemoryStateType>(output.
Type()))
385 return &CallOperation::mapMemoryStateOutputToInput(output);
388 throw std::logic_error(
391 [](
const VariadicArgumentListOperation &) ->
rvsdg::Input *
395 [](
const CallEntryMemoryStateMergeOperation &) -> rvsdg::Input *
399 [](
const AllocaOperation &) -> rvsdg::Input *
403 [&simpleNode]() -> rvsdg::Input *
405 throw std::logic_error(
406 util::strfmt(
"Unhandled operation type: ", simpleNode->DebugString()));
413 auto & targetRegion = context_->getTargetRegion(node);
416 const auto users = getUsersFromTargetRegion(node, targetRegion);
418 std::vector<rvsdg::Output *> operands;
419 operands.reserve(users.size());
423 std::back_inserter(operands),
426 return input->origin();
429 const auto copiedNode = node.
copy(&targetRegion, operands);
433 auto itOrg = std::begin(node.
Outputs());
434 const auto endOrg = std::end(node.
Outputs());
435 auto itCpy = std::begin(copiedNode->Outputs());
436 const auto endCpy = std::end(copiedNode->Outputs());
437 JLM_ASSERT(std::distance(itOrg, endOrg) == std::distance(itCpy, endCpy));
439 for (; itOrg != endOrg; ++itOrg, ++itCpy)
441 auto & outputOrg = *itOrg;
442 auto & outputCpy = *itCpy;
448 outputOrg.divert_users(inputOrg->origin());
453 auto user = users[inputCpy->index()];
454 user->divert_to(&outputCpy);
461 outputOrg.divert_users(&newOutputOrg);
467 outputOrg.divert_users(&newOutputOrg);
471 throw std::logic_error(
util::strfmt(
"Unhandled type kind!"));
483 auto & targetRegion = context_->getTargetRegion(*node);
484 if (&targetRegion != node->region())
486 copyNodeToTargetRegion(*node);
492 for (
auto & subregion : structuralNode->Subregions())
494 hoistNodes(subregion);
511 for (
auto & subregion : structuralNode.
Subregions())
513 printHoistChain(subregion);
518 auto & targetRegion = context_->getTargetRegion(simpleNode);
520 if (&targetRegion != node->region())
522 std::cerr << node->DebugString() <<
"[" << node->GetNodeId() <<
", "
523 << node->region()->getRegionId() <<
"]: ";
524 auto currentRegion = node->region();
527 std::cerr << currentRegion->node()->DebugString() <<
"["
528 << currentRegion->getRegionId() <<
"] -> ";
530 currentRegion = currentRegion->node()->region();
531 }
while (currentRegion != &targetRegion);
533 std::cerr << currentRegion->node()->DebugString() <<
"[" << currentRegion->getRegionId()
539 throw std::logic_error(
"Unhandled node type!");
547 context_ = Context::create(lambdaNode);
565 hoistNodesInLambda(lambdaNode);
569 hoistNodesInRootRegion(*phiNode.subregion());
581 throw std::logic_error(
util::strfmt(
"Unhandled node type: ", node->DebugString()));
589 auto statistics = Statistics::Create(rvsdgModule.
SourceFilePath().value());
591 statistics->start(rvsdgModule.
Rvsdg());
593 statistics->end(rvsdgModule.
Rvsdg());
static jlm::util::StatisticsCollector statisticsCollector
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
Context(rvsdg::LambdaNode &lambdaNode)
rvsdg::Region * LambdaSubregion_
void addTargetRegion(const rvsdg::Node &node, rvsdg::Region ®ion) noexcept
std::unordered_map< const rvsdg::Node *, rvsdg::Region * > TargetRegion_
rvsdg::Region & getTargetRegion(const rvsdg::Node &node) const noexcept
static std::unique_ptr< Context > create(rvsdg::LambdaNode &lambdaNode)
rvsdg::Region & getLambdaSubregion() const noexcept
void end(const rvsdg::Graph &graph) noexcept
Statistics(const util::FilePath &sourceFile)
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
~Statistics() override=default
void start(const rvsdg::Graph &graph) noexcept
Node Hoisting Transformation.
~NodeHoisting() noexcept override
static std::vector< rvsdg::Input * > getUsersFromTargetRegion(rvsdg::Node &node, rvsdg::Region &targetRegion)
rvsdg::Region & computeTargetRegion(const rvsdg::Node &node) const
std::unique_ptr< Context > context_
static bool isInvariantMemoryStateLoopVar(const rvsdg::ThetaNode::LoopVar &loopVar)
void markNodes(const rvsdg::Region ®ion)
static rvsdg::Input & getUserFromTargetRegion(rvsdg::Input &input, rvsdg::Region &targetRegion)
Conditional operator / pattern matching.
Region & GetRootRegion() const noexcept
rvsdg::Region * subregion() const noexcept
NodeOutput * output(size_t index) const noexcept
OutputIteratorRange Outputs() noexcept
virtual const Operation & GetOperation() const noexcept=0
rvsdg::Region * region() const noexcept
InputIteratorRange Inputs() noexcept
size_t ninputs() const noexcept
size_t noutputs() const noexcept
virtual Node * copy(rvsdg::Region *region, const std::vector< jlm::rvsdg::Output * > &operands) const
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
size_t nusers() const noexcept
A phi node represents the fixpoint of mutually recursive definitions.
Represent acyclic RVSDG subgraphs.
void prune(bool recursive)
rvsdg::StructuralNode * node() const noexcept
size_t getDepth() const noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
SubregionIteratorRange Subregions()
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 bool hasOnlyValueInputs(const rvsdg::Node &node)
static rvsdg::Region & limitTargetRegion(const rvsdg::Node &node, rvsdg::Region &targetRegion)
static rvsdg::Input * mapStateOutputToInput(rvsdg::Output &output)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
static bool ThetaLoopVarIsInvariant(const ThetaNode::LoopVar &loopVar) noexcept
Output & RouteToRegion(Output &output, Region ®ion)
@ State
Designate a state type.
@ Value
Designate a value type.
detail::TopDownTraverserGeneric< true > TopDownConstTraverser
Traverser for visiting every node in a const region in a top down order.
size_t ninputs(const rvsdg::Region *region) noexcept
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
detail::TopDownTraverserGeneric< false > TopDownTraverser
Traverser for visiting every node in a region in a top down order.
static std::string strfmt(Args... args)
Description of a loop-carried variable.
rvsdg::Output * pre
Variable before iteration (input argument to subregion).
rvsdg::Output * output
Variable at loop exit (output of theta).
rvsdg::Input * post
Variable after iteration (output result from subregion).