46 static std::unique_ptr<Statistics>
49 return std::make_unique<Statistics>(sourceFile);
92 static std::unique_ptr<Context>
95 return std::make_unique<Context>(lambdaNode);
118 const auto parentRegion = region.
node()->
region();
119 return context_->getRegionDeph(*parentRegion) + 1;
125 if (!is<MemoryStateType>(loopVar.
output->
Type()))
131 const auto userNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*loopVar.
pre->
Users().
begin());
132 const auto originNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*loopVar.
post->
origin());
134 if (userNode != originNode)
144 if (rvsdg::TryGetRegionParentNode<rvsdg::LambdaNode>(output))
150 if (
const auto gammaNode = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(output))
160 const auto roleVar = gammaNode->MapBranchArgument(output);
161 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
170 if (
const auto thetaNode = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(output))
172 const auto loopVar = thetaNode->MapPreLoopVar(output);
187 if (
const auto gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(output))
189 return context_->getTargetRegion(*gammaNode);
193 if (
const auto thetaNode = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(output))
195 return context_->getTargetRegion(*thetaNode);
199 if (
const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(output))
201 return context_->getTargetRegion(*node);
204 throw std::logic_error(
"Unhandled output type!");
221 std::vector<rvsdg::Region *> targetRegions;
222 for (
auto & input : node.
Inputs())
225 if (&targetRegion == node.
region())
232 targetRegions.push_back(&targetRegion);
236 return **std::max_element(
237 targetRegions.begin(),
241 return context_->getRegionDeph(*region1) < context_->getRegionDeph(*region2);
249 context_->addRegionDepth(region, regionDepth);
258 context_->addTargetRegion(structuralNode, *structuralNode.
region());
261 for (
auto & subregion : structuralNode.
Subregions())
263 markNodes(subregion);
269 context_->addTargetRegion(*node, targetRegion);
273 throw std::logic_error(
"Unhandled node type!");
281 if (output.
region() == &targetRegion)
285 if (
const auto gammaNode = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(output))
287 const auto roleVar = gammaNode->MapBranchArgument(output);
288 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
295 if (
const auto thetaNode = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(output))
297 const auto loopVar = thetaNode->MapPreLoopVar(output);
302 throw std::logic_error(
"Unhandled output type!");
305 std::vector<rvsdg::Output *>
308 std::vector<rvsdg::Output *>
operands;
309 for (
auto & input : node.
Inputs())
321 auto & targetRegion =
context_->getTargetRegion(node);
325 const auto copiedNode = node.
copy(&targetRegion,
operands);
329 auto itOrg = std::begin(node.
Outputs());
330 const auto endOrg = std::end(node.
Outputs());
331 auto itCpy = std::begin(copiedNode->Outputs());
332 const auto endCpy = std::end(copiedNode->Outputs());
333 JLM_ASSERT(std::distance(itOrg, endOrg) == std::distance(itCpy, endCpy));
335 for (; itOrg != endOrg; ++itOrg, ++itCpy)
337 auto & outputOrg = *itOrg;
338 auto & outputCpy = *itCpy;
340 outputOrg.divert_users(&newOutputOrg);
351 auto & targetRegion =
context_->getTargetRegion(*node);
352 if (&targetRegion != node->region())
360 for (
auto & subregion : structuralNode->Subregions())
406 throw std::logic_error(
util::strfmt(
"Unhandled node type: ", node->DebugString()));
416 statistics->start(rvsdgModule.
Rvsdg());
418 statistics->end(rvsdgModule.
Rvsdg());
static jlm::util::StatisticsCollector statisticsCollector
std::unordered_map< const rvsdg::Region *, size_t > RegionDepth_
Context(rvsdg::LambdaNode &lambdaNode)
size_t getRegionDeph(const rvsdg::Region ®ion) const noexcept
rvsdg::Region & getLambdaSubregion() const noexcept
rvsdg::Region & getTargetRegion(const rvsdg::Node &node) const noexcept
rvsdg::Region * LambdaSubregion_
void addTargetRegion(const rvsdg::Node &node, rvsdg::Region ®ion) noexcept
void addRegionDepth(const rvsdg::Region ®ion, const size_t depth) noexcept
std::unordered_map< const rvsdg::Node *, rvsdg::Region * > TargetRegion_
static std::unique_ptr< Context > create(rvsdg::LambdaNode &lambdaNode)
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.
void hoistNodesInRootRegion(rvsdg::Region ®ion)
void hoistNodes(rvsdg::Region ®ion)
void hoistNodesInLambda(rvsdg::LambdaNode &lambdaNode)
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
~NodeHoisting() noexcept override
rvsdg::Region & computeTargetRegion(const rvsdg::Node &node) const
static std::vector< rvsdg::Output * > getOperandsFromTargetRegion(rvsdg::Node &node, rvsdg::Region &targetRegion)
std::unique_ptr< Context > context_
static bool isInvariantMemoryStateLoopVar(const rvsdg::ThetaNode::LoopVar &loopVar)
void copyNodeToTargetRegion(rvsdg::Node &node) const
void markNodes(const rvsdg::Region ®ion)
static rvsdg::Output & getOperandFromTargetRegion(rvsdg::Output &output, rvsdg::Region &targetRegion)
size_t computeRegionDepth(const rvsdg::Region ®ion) const
Region & GetRootRegion() const noexcept
rvsdg::Region * subregion() const noexcept
OutputIteratorRange Outputs() noexcept
rvsdg::Region * region() const noexcept
InputIteratorRange Inputs() noexcept
NodeOutput * output(size_t index) const 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.
rvsdg::StructuralNode * node() const noexcept
void prune(bool recursive)
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.
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.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
size_t ninputs(const rvsdg::Region *region) noexcept
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).
static const char * Timer
static const char * NumRvsdgInputsAfter
static const char * NumRvsdgInputsBefore