40 static std::unique_ptr<Statistics>
43 return std::make_unique<Statistics>(sourceFile);
72 for (
auto & output : node.
Outputs())
74 for (
const auto & user : output.Users())
76 const auto successor = rvsdg::TryGetOwnerNode<rvsdg::Node>(user);
77 if (successor != &singleSuccessor)
90 for (
size_t i = 0; i < node->
ninputs(); i++)
93 std::size_t index = 0;
94 for (
auto input : ev.branchArgument)
104 for (
size_t o = 0; o < node->
noutputs(); o++)
108 auto entryvar = std::get<rvsdg::GammaNode::EntryVar>(gamma->
MapInput(user));
109 entryvar.branchArgument[r]->divert_users(copy->output(o));
121 std::vector<rvsdg::GammaNode::EntryVar> entryvars;
122 for (
size_t n = 0; n < node->
noutputs(); n++)
126 entryvars.push_back(std::get<rvsdg::GammaNode::EntryVar>(gamma->
MapInput(user)));
139 while (index < evs.size())
141 const auto & ev = evs[index];
142 auto node = rvsdg::TryGetOwnerNode<rvsdg::Node>(*ev.input->origin());
143 auto tmp = rvsdg::TryGetOwnerNode<rvsdg::Node>(*gamma->
predicate()->
origin());
166 for (
auto & output : node.
Outputs())
168 for (
auto & user : output.Users())
170 if (
const auto userNode = rvsdg::TryGetOwnerNode<rvsdg::Node>(user))
172 if (dependentNodes.insert(userNode))
174 collect(*userNode, dependentNodes);
182 collect(node, dependentNodes);
183 return dependentNodes;
186 std::vector<rvsdg::Node *>
194 std::vector<rvsdg::Node *> sortedNodes;
195 for (
auto & node : nodes.
Items())
197 sortedNodes.push_back(node);
204 [&depthMap](
const auto * node1,
const auto * node2)
206 JLM_ASSERT(depthMap.find(node1) != depthMap.end());
207 JLM_ASSERT(depthMap.find(node2) != depthMap.end());
208 return depthMap[node1] < depthMap[node2];
218 const auto sortedDependentNodes =
sortByDepth(dependentNodes);
223 for (
auto & node : sortedDependentNodes)
226 std::unordered_map<rvsdg::Region *, std::vector<rvsdg::Output *>> subregionOperands;
227 for (
auto & input : node->Inputs())
229 auto & oldOperand = *input.origin();
230 if (rvsdg::TryGetOwnerNode<rvsdg::Node>(oldOperand) == &gammaNode)
233 for (
const auto branchResult : branchResults)
235 subregionOperands[branchResult->region()].push_back(branchResult->origin());
240 auto [_, branchArguments] = gammaNode.
AddEntryVar(&oldOperand);
241 for (
auto branchArgument : branchArguments)
243 subregionOperands[branchArgument->region()].push_back(branchArgument);
249 std::unordered_map<rvsdg::Region *, std::vector<rvsdg::Output *>> subregionOutputs;
250 for (
auto & subregion : gammaNode.
Subregions())
252 const auto copiedNode = node->copy(&subregion, subregionOperands.at(&subregion));
257 for (
auto & output : node->Outputs())
259 std::vector<rvsdg::Output *> branchResultOperands;
260 for (
auto & subregion : gammaNode.
Subregions())
262 branchResultOperands.push_back(subregionOutputs[&subregion][output.index()]);
265 auto [_, exitVarOutput] = gammaNode.
AddExitVar(branchResultOperands);
266 output.divert_users(exitVarOutput);
270 return dependentNodes.Size();
279 std::unordered_set<const rvsdg::Input *> inputs;
280 for (
size_t n = 0; n < node->
noutputs(); n++)
284 inputs.insert(&user);
289 std::unordered_set<rvsdg::Region *> subregions;
290 for (
const auto & input : inputs)
293 [&subregions](
const auto & rolevar)
297 for (
const auto & argument : rolevar.branchArgument)
299 if (argument->nusers() != 0)
300 subregions.insert(argument->region());
303 else if constexpr (std::is_same<
304 std::decay_t<decltype(rolevar)>,
307 for (
const auto & argument : rolevar.matchContent)
309 if (argument->nusers() != 0)
310 subregions.insert(argument->region());
315 JLM_UNREACHABLE(
"A gamma input must either be the match variable or an entry variable");
321 return subregions.size();
334 auto prednode = rvsdg::TryGetOwnerNode<rvsdg::Node>(*gamma->
predicate()->
origin());
339 while (index < evs.size())
341 const auto & ev = evs[index];
342 auto node = rvsdg::TryGetOwnerNode<rvsdg::Node>(*ev.input->origin());
377 for (
size_t n = 0; n < structnode->nsubregions(); n++)
378 pull(structnode->subregion(n));
388 statistics->start(module.
Rvsdg());
390 statistics->end(module.
Rvsdg());
398 NodeSinking::Run(rvsdg::RvsdgModule & module, util::StatisticsCollector & statisticsCollector)
400 pull(module, statisticsCollector);
void end(const rvsdg::Graph &graph) noexcept
~Statistics() override=default
Statistics(const util::FilePath &sourceFile)
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void start(const rvsdg::Graph &graph) noexcept
Node Sinking Optimization.
static std::vector< rvsdg::Node * > sortByDepth(const util::HashSet< rvsdg::Node * > &nodes)
static util::HashSet< rvsdg::Node * > collectDependentNodes(const rvsdg::Node &node)
static size_t sinkDependentNodesIntoGamma(rvsdg::GammaNode &gammaNode)
~NodeSinking() noexcept override
Conditional operator / pattern matching.
void RemoveEntryVars(const std::vector< EntryVar > &entryVars)
Removes the given entry variables.
ExitVar MapOutputExitVar(const rvsdg::Output &output) const
Maps gamma output to exit variable description.
std::variant< MatchVar, EntryVar > MapInput(const rvsdg::Input &input) const
Maps gamma input to its role (match variable or entry variable).
EntryVar AddEntryVar(rvsdg::Output *origin)
Routes a variable into the gamma branches.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
ExitVar AddExitVar(std::vector< rvsdg::Output * > values)
Routes per-branch result of gamma to output.
rvsdg::Input * predicate() const noexcept
Region & GetRootRegion() const noexcept
OutputIteratorRange Outputs() noexcept
NodeInput * input(size_t index) const 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
Represent acyclic RVSDG subgraphs.
size_t numNodes() const noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
SubregionIteratorRange Subregions()
size_t nsubregions() const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
IteratorRange< ItemConstIterator > Items() const noexcept
bool IsEmpty() 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)
#define JLM_UNREACHABLE(msg)
Global memory state passed between functions.
static void pullin_node(rvsdg::GammaNode *gamma, rvsdg::Node *node)
static void cleanup(rvsdg::GammaNode *gamma, rvsdg::Node *node)
static size_t is_used_in_nsubregions(const rvsdg::GammaNode *gamma, const rvsdg::Node *node)
static bool empty(const rvsdg::GammaNode *gamma)
void pullin_top(rvsdg::GammaNode *gamma)
static bool isSingleSuccessor(const rvsdg::Node &node, const rvsdg::Node &singleSuccessor)
void pull(rvsdg::GammaNode *gamma)
static void remove(Node *node)
std::unordered_map< const Node *, size_t > computeDepthMap(const Region ®ion)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
size_t ninputs(const rvsdg::Region *region) noexcept
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
A variable routed into all gamma regions.
The match/discriminator variable of this gamma node.
static const char * Timer
static const char * NumRvsdgInputsAfter
static const char * NumRvsdgInputsBefore