45 static std::unique_ptr<Statistics>
48 return std::make_unique<Statistics>(sourceFile);
91 static std::unique_ptr<Context>
94 return std::make_unique<Context>(lambdaNode);
117 const auto parentRegion = region.
node()->
region();
118 return context_->getRegionDeph(*parentRegion) + 1;
124 if (!is<MemoryStateType>(loopVar.
output->
Type()))
130 const auto userNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*loopVar.
pre->
Users().
begin());
131 const auto originNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*loopVar.
post->
origin());
133 if (userNode != originNode)
143 if (rvsdg::TryGetRegionParentNode<rvsdg::LambdaNode>(output))
149 if (
const auto gammaNode = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(output))
159 const auto roleVar = gammaNode->MapBranchArgument(output);
160 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
169 if (
const auto thetaNode = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(output))
171 const auto loopVar = thetaNode->MapPreLoopVar(output);
186 if (
const auto gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(output))
188 return context_->getTargetRegion(*gammaNode);
192 if (
const auto thetaNode = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(output))
194 return context_->getTargetRegion(*thetaNode);
198 if (
const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(output))
200 return context_->getTargetRegion(*node);
203 throw std::logic_error(
"Unhandled output type!");
220 std::vector<rvsdg::Region *> targetRegions;
221 for (
auto & input : node.
Inputs())
224 if (&targetRegion == node.
region())
231 targetRegions.push_back(&targetRegion);
235 return **std::max_element(
236 targetRegions.begin(),
240 return context_->getRegionDeph(*region1) < context_->getRegionDeph(*region2);
248 context_->addRegionDepth(region, regionDepth);
257 context_->addTargetRegion(structuralNode, *structuralNode.
region());
260 for (
auto & subregion : structuralNode.
Subregions())
262 markNodes(subregion);
268 context_->addTargetRegion(*node, targetRegion);
272 throw std::logic_error(
"Unhandled node type!");
280 if (output.
region() == &targetRegion)
284 if (
const auto gammaNode = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(output))
286 const auto roleVar = gammaNode->MapBranchArgument(output);
287 if (
const auto entryVar = std::get_if<rvsdg::GammaNode::EntryVar>(&roleVar))
294 if (
const auto thetaNode = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(output))
296 const auto loopVar = thetaNode->MapPreLoopVar(output);
301 throw std::logic_error(
"Unhandled output type!");
304 std::vector<rvsdg::Output *>
307 std::vector<rvsdg::Output *>
operands;
308 for (
auto & input : node.
Inputs())
320 auto & targetRegion =
context_->getTargetRegion(node);
324 const auto copiedNode = node.
copy(&targetRegion,
operands);
328 auto itOrg = std::begin(node.
Outputs());
329 const auto endOrg = std::end(node.
Outputs());
330 auto itCpy = std::begin(copiedNode->Outputs());
331 const auto endCpy = std::end(copiedNode->Outputs());
332 JLM_ASSERT(std::distance(itOrg, endOrg) == std::distance(itCpy, endCpy));
334 for (; itOrg != endOrg; ++itOrg, ++itCpy)
336 auto & outputOrg = *itOrg;
337 auto & outputCpy = *itCpy;
339 outputOrg.divert_users(&newOutputOrg);
350 auto & targetRegion =
context_->getTargetRegion(*node);
351 if (&targetRegion != node->region())
359 for (
auto & subregion : structuralNode->Subregions())
405 throw std::logic_error(
util::strfmt(
"Unhandled node type: ", node->DebugString()));
415 statistics->start(rvsdgModule.
Rvsdg());
417 statistics->end(rvsdgModule.
Rvsdg());
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