26 const char * MarkTimerLabel_ =
"MarkTime";
27 const char * DivertTimerLabel_ =
"DivertTime";
39 AddMeasurement(Label::NumRvsdgNodesBefore,
rvsdg::nnodes(&graph.GetRootRegion()));
40 AddMeasurement(Label::NumRvsdgInputsBefore,
rvsdg::ninputs(&graph.GetRootRegion()));
41 AddTimer(MarkTimerLabel_).start();
47 GetTimer(MarkTimerLabel_).stop();
53 AddTimer(DivertTimerLabel_).start();
59 AddMeasurement(Label::NumRvsdgNodesAfter,
rvsdg::nnodes(&graph.GetRootRegion()));
60 AddMeasurement(Label::NumRvsdgInputsAfter,
rvsdg::ninputs(&graph.GetRootRegion()));
61 GetTimer(DivertTimerLabel_).stop();
64 static std::unique_ptr<Statistics>
67 return std::make_unique<Statistics>(sourceFile);
85 if (s2->size() < s1->size())
103 for (
size_t n = 0; n < n1->
noutputs(); n++)
113 auto it = outputs_.find(o1);
114 if (it == outputs_.end())
117 return it->second->find(o2) != it->second->end();
123 return congruent(i1->origin(), i2->origin());
129 if (outputs_.find(output) == outputs_.end())
131 std::unique_ptr<congruence_set> set(
new congruence_set({ output }));
132 outputs_[output] = set.get();
133 sets_.insert(std::move(set));
136 return outputs_[output];
140 std::unordered_set<std::unique_ptr<congruence_set>>
sets_;
141 std::unordered_map<const jlm::rvsdg::Output *, congruence_set *>
outputs_;
150 auto it = sets_.find(o1);
151 if (it != sets_.end())
152 sets_[o1].insert(o2);
157 if (it != sets_.end())
158 sets_[o2].insert(o1);
166 auto it = sets_.find(o1);
167 if (it == sets_.end())
170 return it->second.find(o2) != it->second.end();
174 std::unordered_map<const jlm::rvsdg::Output *, std::unordered_set<const jlm::rvsdg::Output *>>
189 if (
auto theta1 = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*o1))
191 if (
auto theta2 = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*o2))
194 auto loopvar1 = theta1->MapPreLoopVar(*o1);
195 auto loopvar2 = theta2->MapPreLoopVar(*o2);
197 auto i1 = loopvar1.input, i2 = loopvar2.input;
198 if (!
congruent(loopvar1.input->origin(), loopvar2.input->origin(), vs, ctx))
203 return congruent(output1, output2, vs, ctx);
207 if (
auto theta1 = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*o1))
209 if (
auto theta2 = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*o2))
211 if (theta1 == theta2)
214 auto loopvar1 = theta1->MapOutputLoopVar(*o1);
215 auto loopvar2 = theta2->MapOutputLoopVar(*o2);
216 auto r1 = loopvar1.post;
217 auto r2 = loopvar2.post;
218 return congruent(r1->origin(), r2->origin(), vs, ctx);
223 auto n1 = TryGetOwnerNode<Node>(*o1);
224 auto n2 = TryGetOwnerNode<Node>(*o2);
228 if (a1 &&
dynamic_cast<const LoopNode *
>(a1->region()->node()) && a2
229 &&
dynamic_cast<const LoopNode *
>(a2->region()->node()))
232 if (a1->input() && a2->input())
236 return congruent(a1->input()->origin(), a2->input()->origin(), vs, ctx);
245 auto r2 = so2->results.begin();
246 for (; r1 != so1->results.end(); r1++, r2++)
249 if (!
congruent(r1->origin(), r2->origin(), vs, ctx))
255 if (
auto g1 = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(*o1))
257 if (
auto g2 = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(*o2))
260 auto origin1 = std::visit(
263 return rolevar.input->origin();
265 g1->MapBranchArgument(*o1));
266 auto origin2 = std::visit(
269 return rolevar.input->origin();
271 g2->MapBranchArgument(*o2));
272 return congruent(origin1, origin2, vs, ctx);
276 if (jlm::rvsdg::is<SimpleOperation>(n1) && jlm::rvsdg::is<SimpleOperation>(n2)
277 && n1->GetOperation() == n2->GetOperation() && n1->ninputs() == n2->ninputs()
280 for (
size_t n = 0; n < n1->ninputs(); n++)
282 auto origin1 = n1->input(n)->origin();
283 auto origin2 = n2->input(n)->origin();
284 if (!
congruent(origin1, origin2, vs, ctx))
312 ctx.
mark(a1.ptr(), a2.ptr());
323 for (
size_t i1 = 1; i1 < node->
ninputs(); i1++)
325 for (
size_t i2 = i1 + 1; i2 < node->
ninputs(); i2++)
333 for (
size_t o1 = 0; o1 < node->
noutputs(); o1++)
335 for (
size_t o2 = o1 + 1; o2 < node->
noutputs(); o2++)
347 for (
size_t i1 = 0; i1 < theta->
ninputs(); i1++)
349 for (
size_t i2 = i1 + 1; i2 < theta->
ninputs(); i2++)
351 auto input1 = theta->
input(i1);
352 auto input2 = theta->
input(i2);
355 if (
congruent(loopvar1.pre, loopvar2.pre, ctx))
357 ctx.
mark(loopvar1.pre, loopvar2.pre);
358 ctx.
mark(loopvar1.output, loopvar2.output);
370 for (
size_t i1 = 0; i1 < loop->
ninputs(); i1++)
372 for (
size_t i2 = i1 + 1; i2 < loop->
ninputs(); i2++)
374 auto input1 = loop->
input(i1);
375 auto input2 = loop->
input(i2);
376 if (
congruent(input1->arguments.first(), input2->arguments.first(), ctx))
378 ctx.
mark(input1->arguments.first(), input2->arguments.first());
389 for (
size_t i1 = 0; i1 < node->
ninputs(); i1++)
391 for (
size_t i2 = i1 + 1; i2 < node->
ninputs(); i2++)
393 auto input1 = node->
input(i1);
394 auto input2 = node->
input(i2);
396 ctx.
mark(input1->arguments.first(), input2->arguments.first());
409 for (
size_t i1 = 0; i1 < ctxvars.size(); ++i1)
411 for (
size_t i2 = i1 + 1; i2 < ctxvars.size(); ++i2)
413 if (ctx.
congruent(ctxvars[i1].input, ctxvars[i2].input))
415 ctx.
mark(ctxvars[i1].inner, ctxvars[i2].inner);
458 if (&other != node && node->
GetOperation() == other.GetOperation())
460 ctx.
mark(node, &other);
468 for (
const auto & origin : *set)
470 for (
const auto & user : origin->Users())
472 const auto other = TryGetOwnerNode<rvsdg::Node>(user);
474 || other->ninputs() != node->
ninputs())
478 for (n = 0; n < node->
ninputs(); n++)
484 ctx.
mark(node, other);
506 auto set = ctx.
set(output);
507 for (
auto & other : *set)
508 other->divert_users(output);
515 for (
size_t n = 0; n < node->
noutputs(); n++)
522 for (
size_t n = 0; n < region->
narguments(); n++)
534 for (
auto input : ev.branchArgument)
625 util::StatisticsCollector & statisticsCollector)
627 const auto & graph = module.Rvsdg();
630 auto statistics = Statistics::Create(module.SourceFilePath().value());
632 statistics->start_mark_stat(graph);
633 mark(&graph.GetRootRegion(), ctx);
634 statistics->end_mark_stat();
636 statistics->start_divert_stat();
637 divert(&graph.GetRootRegion(), ctx);
638 statistics->end_divert_stat(graph);
640 statisticsCollector.CollectDemandedStatistics(std::move(statistics));
~Statistics() override=default
Statistics(const util::FilePath &sourceFile)
void start_mark_stat(const Graph &graph) noexcept
void end_divert_stat(const Graph &graph) noexcept
void start_divert_stat() noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void end_mark_stat() noexcept
Common Node Elimination This is mainly a copy of the CNE optimization in the LLVM backend with the ad...
~CommonNodeElimination() noexcept override
std::unordered_set< std::unique_ptr< congruence_set > > sets_
void mark(const Node *n1, const Node *n2)
bool congruent(jlm::rvsdg::Output *o1, jlm::rvsdg::Output *o2) const noexcept
congruence_set * set(jlm::rvsdg::Output *output) noexcept
std::unordered_map< const jlm::rvsdg::Output *, congruence_set * > outputs_
void mark(jlm::rvsdg::Output *o1, jlm::rvsdg::Output *o2)
bool congruent(const jlm::rvsdg::Input *i1, const jlm::rvsdg::Input *i2) const noexcept
rvsdg::Region * subregion() const noexcept
std::unordered_map< const jlm::rvsdg::Output *, std::unordered_set< const jlm::rvsdg::Output * > > sets_
void insert(const jlm::rvsdg::Output *o1, const jlm::rvsdg::Output *o2)
bool visited(const jlm::rvsdg::Output *o1, const jlm::rvsdg::Output *o2) const
Conditional operator / pattern matching.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
rvsdg::Region * subregion() const noexcept
rvsdg::Region * region() const noexcept
NodeOutput * output(size_t index) const noexcept
size_t ninputs() const noexcept
size_t noutputs() const noexcept
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
size_t index() const noexcept
A phi node represents the fixpoint of mutually recursive definitions.
rvsdg::Region * subregion() const noexcept
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
Represents the argument of a region.
Represent acyclic RVSDG subgraphs.
rvsdg::StructuralNode * node() const noexcept
TopNodeRange TopNodes() noexcept
RegionArgument * argument(size_t index) const noexcept
size_t narguments() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
SubregionIteratorRange Subregions()
size_t nsubregions() const noexcept
StructuralOutput * output(size_t index) const noexcept
StructuralInput * input(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
rvsdg::Region * subregion() const noexcept
LoopVar MapInputLoopVar(const rvsdg::Input &input) const
Maps variable at entry to full varibale description.
size_type size() const noexcept
Iterator begin() noexcept
static void mark_arguments(StructuralInput *i1, StructuralInput *i2, Context &ctx)
static void divert_gamma(rvsdg::GammaNode *gamma, Context &ctx)
static void mark_theta(const rvsdg::ThetaNode *theta, Context &ctx)
static void mark_gamma(const rvsdg::GammaNode *node, Context &ctx)
static void divert(rvsdg::Region *, Context &)
static void divert_theta(rvsdg::ThetaNode *theta, Context &ctx)
static void divert_arguments(rvsdg::Region *region, Context &ctx)
std::unordered_set< jlm::rvsdg::Output * > congruence_set
static void divert_users(jlm::rvsdg::Output *output, Context &ctx)
static bool congruent(Output *o1, Output *o2, VisitorSet &vs, Context &ctx)
static void mark_phi(const rvsdg::PhiNode *phi, Context &ctx)
static void mark_lambda(const rvsdg::LambdaNode *node, Context &ctx)
static void divert_outputs(Node *node, Context &ctx)
static void divert_lambda(rvsdg::LambdaNode *node, Context &ctx)
static void divert_loop(LoopNode *node, Context &ctx)
static void mark_loop(const LoopNode *loop, Context &ctx)
static void divert_phi(rvsdg::PhiNode *phi, Context &ctx)
static void mark(jlm::rvsdg::Region *, Context &)
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
size_t nnodes(const jlm::rvsdg::Region *region) noexcept
size_t ninputs(const rvsdg::Region *region) noexcept
detail::TopDownTraverserGeneric< false > TopDownTraverser
Traverser for visiting every node in a region in a top down order.