6 #include <gtest/gtest.h>
23 TEST(CommonNodeEliminationTests, test_simple)
31 auto & graph = rm.
Rvsdg();
37 auto n1 = TestOperation::createNode(&graph.GetRootRegion(), {}, { vt })->output(0);
38 auto n2 = TestOperation::createNode(&graph.GetRootRegion(), {}, { vt })->output(0);
40 auto u1 = TestOperation::createNode(&graph.GetRootRegion(), { z }, { vt })->output(0);
42 auto b1 = TestOperation::createNode(&graph.GetRootRegion(), { x, y }, { vt })->output(0);
43 auto b2 = TestOperation::createNode(&graph.GetRootRegion(), { x, y }, { vt })->output(0);
44 auto b3 = TestOperation::createNode(&graph.GetRootRegion(), { n1, z }, { vt })->output(0);
45 auto b4 = TestOperation::createNode(&graph.GetRootRegion(), { n2, z }, { vt })->output(0);
60 EXPECT_EQ(graph.GetRootRegion().result(0)->origin(), graph.GetRootRegion().result(1)->origin());
61 EXPECT_EQ(graph.GetRootRegion().result(3)->origin(), graph.GetRootRegion().result(4)->origin());
62 EXPECT_EQ(graph.GetRootRegion().result(5)->origin(), graph.GetRootRegion().result(6)->origin());
65 TEST(CommonNodeEliminationTests, test_gamma)
74 auto & graph = rm.
Rvsdg();
81 auto u1 = TestOperation::createNode(&graph.GetRootRegion(), { x }, { vt })->output(0);
82 auto u2 = TestOperation::createNode(&graph.GetRootRegion(), { x }, { vt })->output(0);
86 auto ev1 = gamma->AddEntryVar(u1);
87 auto ev2 = gamma->AddEntryVar(u2);
88 auto ev3 = gamma->AddEntryVar(y);
89 auto ev4 = gamma->AddEntryVar(z);
90 auto ev5 = gamma->AddEntryVar(z);
92 auto n1 = TestOperation::createNode(gamma->subregion(0), {}, { vt })->output(0);
93 auto n2 = TestOperation::createNode(gamma->subregion(0), {}, { vt })->output(0);
94 auto n3 = TestOperation::createNode(gamma->subregion(0), {}, { vt })->output(0);
96 gamma->AddExitVar({ ev1.branchArgument[0], ev1.branchArgument[1] });
97 gamma->AddExitVar({ ev2.branchArgument[0], ev2.branchArgument[1] });
98 gamma->AddExitVar({ ev3.branchArgument[0], ev3.branchArgument[1] });
99 gamma->AddExitVar({ n1, ev3.branchArgument[1] });
100 gamma->AddExitVar({ n2, ev3.branchArgument[1] });
101 gamma->AddExitVar({ n3, ev3.branchArgument[1] });
102 gamma->AddExitVar({ ev5.branchArgument[0], ev4.branchArgument[1] });
113 auto subregion0 = gamma->subregion(0);
114 auto subregion1 = gamma->subregion(1);
115 EXPECT_EQ(gamma->input(1)->origin(), gamma->input(2)->origin());
116 EXPECT_EQ(subregion0->result(0)->origin(), subregion0->result(1)->origin());
117 EXPECT_EQ(subregion0->result(3)->origin(), subregion0->result(4)->origin());
118 EXPECT_EQ(subregion0->result(3)->origin(), subregion0->result(5)->origin());
119 EXPECT_EQ(subregion1->result(0)->origin(), subregion1->result(1)->origin());
120 EXPECT_EQ(graph.GetRootRegion().result(0)->origin(), graph.GetRootRegion().result(1)->origin());
126 EXPECT_EQ(argument0->input(), argument1->input());
129 TEST(CommonNodeEliminationTests, test_gamma_congruent_exit_vars)
162 auto & graph = rm.
Rvsdg();
170 auto entryVarA = gamma->AddEntryVar(importA);
171 auto entryVarB = gamma->AddEntryVar(importB);
174 auto exitVarA = gamma->AddExitVar({ entryVarA.branchArgument[0], entryVarA.branchArgument[1] });
175 auto exitVarB = gamma->AddExitVar({ entryVarB.branchArgument[0], entryVarB.branchArgument[1] });
178 auto exitVarX = gamma->AddExitVar({ entryVarA.branchArgument[0], entryVarB.branchArgument[1] });
179 auto exitVarY = gamma->AddExitVar({ entryVarA.branchArgument[0], entryVarB.branchArgument[1] });
180 auto exitVarZ = gamma->AddExitVar({ entryVarB.branchArgument[0], entryVarA.branchArgument[1] });
195 EXPECT_EQ(exportA.origin(), importA);
196 EXPECT_EQ(exportB.origin(), importB);
199 EXPECT_EQ(exportX.origin(), exitVarX.output);
200 EXPECT_EQ(exportY.origin(), exitVarX.output);
201 EXPECT_EQ(exitVarY.output->nusers(), 0u);
204 EXPECT_EQ(exportZ.origin(), exitVarZ.output);
207 TEST(CommonNodeEliminationTests, test_theta)
216 auto & graph = rm.
Rvsdg();
222 auto region = theta->subregion();
224 auto lv1 = theta->AddLoopVar(c);
225 auto lv2 = theta->AddLoopVar(x);
226 auto lv3 = theta->AddLoopVar(x);
227 auto lv4 = theta->AddLoopVar(x);
229 auto u1 = TestOperation::createNode(region, { lv2.pre }, {
vt })->output(0);
230 auto u2 = TestOperation::createNode(region, { lv3.pre }, {
vt })->output(0);
231 auto b1 = TestOperation::createNode(region, { lv3.pre, lv4.pre }, {
vt })->output(0);
233 lv2.post->divert_to(u1);
234 lv3.post->divert_to(u2);
235 lv4.post->divert_to(b1);
237 theta->set_predicate(lv1.pre);
248 auto un1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*u1);
249 auto un2 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*u2);
250 auto bn1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*b1);
251 EXPECT_EQ(un1->input(0)->origin(), un2->input(0)->origin());
252 EXPECT_EQ(bn1->input(0)->origin(), un1->input(0)->origin());
253 EXPECT_EQ(bn1->input(1)->origin(), region->argument(3));
254 EXPECT_EQ(region->result(2)->origin(), region->result(3)->origin());
255 EXPECT_EQ(graph.GetRootRegion().result(0)->origin(), graph.GetRootRegion().result(1)->origin());
258 TEST(CommonNodeEliminationTests, test_theta2)
267 auto & graph = rm.
Rvsdg();
273 auto region = theta->subregion();
275 auto lv1 = theta->AddLoopVar(c);
276 auto lv2 = theta->AddLoopVar(x);
277 auto lv3 = theta->AddLoopVar(x);
279 auto u1 = TestOperation::createNode(region, { lv2.pre }, {
vt })->output(0);
280 auto u2 = TestOperation::createNode(region, { lv3.pre }, {
vt })->output(0);
281 auto b1 = TestOperation::createNode(region, { u2, u2 }, {
vt })->output(0);
283 lv2.post->divert_to(u1);
284 lv3.post->divert_to(b1);
286 theta->set_predicate(lv1.pre);
296 EXPECT_EQ(lv2.post->origin(), u1);
297 EXPECT_NE(lv2.pre->nusers(), 0u);
298 EXPECT_NE(lv3.pre->nusers(), 0u);
301 TEST(CommonNodeEliminationTests, test_theta3)
310 auto & graph = rm.
Rvsdg();
316 auto r1 = theta1->subregion();
318 auto lv1 = theta1->AddLoopVar(c);
319 auto lv2 = theta1->AddLoopVar(x);
320 auto lv3 = theta1->AddLoopVar(x);
321 auto lv4 = theta1->AddLoopVar(x);
324 auto r2 = theta2->subregion();
325 auto p = theta2->AddLoopVar(lv1.pre);
326 auto p2 = theta2->AddLoopVar(lv2.pre);
327 auto p3 = theta2->AddLoopVar(lv3.pre);
328 auto p4 = theta2->AddLoopVar(lv4.pre);
329 theta2->set_predicate(p.pre);
331 auto u1 = TestOperation::createNode(r1, { p2.output }, {
vt });
332 auto b1 = TestOperation::createNode(r1, { p3.output, p3.output }, {
vt });
333 auto u2 = TestOperation::createNode(r1, { p4.output }, {
vt });
335 lv2.post->divert_to(u1->output(0));
336 lv3.post->divert_to(b1->output(0));
337 lv4.post->divert_to(u1->output(0));
339 theta1->set_predicate(lv1.pre);
350 EXPECT_EQ(r1->result(2)->origin(), r1->result(4)->origin());
351 EXPECT_EQ(u1->input(0)->origin(), u2->input(0)->origin());
352 EXPECT_EQ(r2->result(2)->origin(), r2->result(4)->origin());
353 EXPECT_EQ(theta2->input(1)->origin(), theta2->input(3)->origin());
354 EXPECT_NE(r1->result(3)->origin(), r1->result(4)->origin());
355 EXPECT_NE(r2->result(3)->origin(), r2->result(4)->origin());
358 TEST(CommonNodeEliminationTests, test_theta4)
367 auto & graph = rm.
Rvsdg();
374 auto region = theta->subregion();
376 auto lv1 = theta->AddLoopVar(c);
377 auto lv2 = theta->AddLoopVar(x);
378 auto lv3 = theta->AddLoopVar(x);
379 auto lv4 = theta->AddLoopVar(y);
380 auto lv5 = theta->AddLoopVar(y);
381 auto lv6 = theta->AddLoopVar(x);
382 auto lv7 = theta->AddLoopVar(x);
384 auto u1 = TestOperation::createNode(region, { lv2.pre }, {
vt });
385 auto b1 = TestOperation::createNode(region, { lv3.pre, lv3.pre }, {
vt });
387 lv2.post->divert_to(lv4.pre);
388 lv3.post->divert_to(lv5.pre);
389 lv4.post->divert_to(u1->output(0));
390 lv5.post->divert_to(b1->output(0));
392 theta->set_predicate(lv1.pre);
404 EXPECT_NE(ex1.origin(), ex2.origin());
405 EXPECT_NE(lv2.pre->nusers(), 0u);
406 EXPECT_NE(lv3.pre->nusers(), 0u);
407 EXPECT_EQ(lv6.post->origin(), lv7.post->origin());
410 TEST(CommonNodeEliminationTests, test_theta5)
418 auto & graph = rm.
Rvsdg();
425 auto region = theta->subregion();
427 auto lv0 = theta->AddLoopVar(c);
428 auto lv1 = theta->AddLoopVar(x);
429 auto lv2 = theta->AddLoopVar(x);
430 auto lv3 = theta->AddLoopVar(y);
431 auto lv4 = theta->AddLoopVar(y);
433 lv1.post->divert_to(lv3.pre);
434 lv2.post->divert_to(lv4.pre);
436 theta->set_predicate(lv0.pre);
448 EXPECT_EQ(ex1.origin(), ex2.origin());
449 EXPECT_EQ(ex3.origin(), ex4.origin());
450 EXPECT_EQ(region->result(4)->origin(), region->result(5)->origin());
451 EXPECT_EQ(region->result(2)->origin(), region->result(3)->origin());
454 TEST(CommonNodeEliminationTests, MultipleThetas)
460 const auto valueType = TestType::createValueType();
463 auto & rvsdg = rvsdgModule.
Rvsdg();
468 auto thetaNode1 = ThetaNode::create(&rvsdg.GetRootRegion());
469 auto loopVariable1 = thetaNode1->AddLoopVar(&i0);
471 TestOperation::createNode(thetaNode1->subregion(), { loopVariable1.pre }, { valueType });
472 loopVariable1.post->divert_to(node1->output(0));
475 auto thetaNode2 = ThetaNode::create(&rvsdg.GetRootRegion());
476 auto predicate = &ControlConstantOperation::create(*thetaNode2->subregion(), 2, 1);
477 thetaNode2->set_predicate(predicate);
478 auto loopVariable2 = thetaNode2->AddLoopVar(&i0);
480 TestOperation::createNode(thetaNode1->subregion(), { loopVariable2.pre }, { valueType });
481 loopVariable2.post->divert_to(node2->output(0));
484 auto thetaNode3 = ThetaNode::create(&rvsdg.GetRootRegion());
485 auto loopVariable3 = thetaNode3->AddLoopVar(loopVariable1.output);
486 auto loopVariable4 = thetaNode3->AddLoopVar(loopVariable2.output);
502 EXPECT_NE(x1.origin(), x2.origin());
505 TEST(CommonNodeEliminationTests, MultipleThetasPassthrough)
511 const auto valueType = TestType::createValueType();
514 auto & rvsdg = rvsdgModule.
Rvsdg();
519 auto thetaNode1 = ThetaNode::create(&rvsdg.GetRootRegion());
520 auto loopVariable1 = thetaNode1->AddLoopVar(&i0);
523 auto thetaNode2 = ThetaNode::create(&rvsdg.GetRootRegion());
524 auto predicate = &ControlConstantOperation::create(*thetaNode2->subregion(), 2, 1);
525 thetaNode2->set_predicate(predicate);
526 auto loopVariable2 = thetaNode2->AddLoopVar(&i0);
529 auto thetaNode3 = ThetaNode::create(&rvsdg.GetRootRegion());
530 auto loopVariable3 = thetaNode3->AddLoopVar(loopVariable1.output);
531 auto loopVariable4 = thetaNode3->AddLoopVar(loopVariable2.output);
548 EXPECT_EQ(x1.origin(), x2.origin());
551 TEST(CommonNodeEliminationTests, test_lambda)
560 auto & graph = rm.Rvsdg();
565 graph.GetRootRegion(),
568 auto d1 = lambda->AddContextVar(*x).inner;
569 auto d2 = lambda->AddContextVar(*x).inner;
571 auto b1 = TestOperation::createNode(lambda->subregion(), { d1, d2 }, { vt })->output(0);
573 auto output = lambda->finalize({ b1 });
582 auto bn1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*b1);
583 EXPECT_EQ(bn1->input(0)->origin(), bn1->input(1)->origin());
586 TEST(CommonNodeEliminationTests, test_phi)
594 auto & graph = rm.Rvsdg();
599 pb.
begin(&graph.GetRootRegion());
611 auto cv1 = lambda1->AddContextVar(*d1.inner).inner;
612 auto f1 = lambda1->finalize({ cv1 });
617 auto cv2 = lambda2->AddContextVar(*d2.inner).inner;
618 auto f2 = lambda2->finalize({ cv2 });
620 r1.result->divert_to(f1);
621 r2.result->divert_to(f2);
634 jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*f1).input(0)->origin(),
635 jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*f2).input(0)->origin());
638 TEST(CommonNodeEliminationTests, EmptyTheta)
644 auto valueType = TestType::createValueType();
645 auto controlType = ControlType::Create(2);
648 auto & rvsdg = rvsdgModule.
Rvsdg();
650 auto thetaNode = ThetaNode::create(&rvsdg.GetRootRegion());
652 auto node1 = TestOperation::createNode(thetaNode->subregion(), {}, { valueType });
654 TestOperation::createNode(thetaNode->subregion(), { node1->output(0) }, { valueType });
656 TestOperation::createNode(thetaNode->subregion(), { node1->output(0) }, { valueType });
657 auto node4 = TestOperation::createNode(
658 thetaNode->subregion(),
659 { node2->output(0), node3->output(0) },
662 thetaNode->set_predicate(node4->output(0));
670 thetaNode->subregion()->prune(
false);
676 EXPECT_EQ(thetaNode->subregion()->numNodes(), 3u);
679 TEST(CommonNodeEliminationTests, GammaInTheta)
709 const auto valueType = TestType::createValueType();
712 auto & rvsdg = rvsdgModule.
Rvsdg();
714 auto & constant10 = BitConstantOperation::create(rvsdg.GetRootRegion(), { 32, 10 });
716 auto thetaNode = ThetaNode::create(&rvsdg.GetRootRegion());
717 auto loopVar1 = thetaNode->AddLoopVar(&constant10);
718 auto loopVar2 = thetaNode->AddLoopVar(&constant10);
719 auto & thetaRegion = *thetaNode->subregion();
721 auto & control0 = ControlConstantOperation::create(thetaRegion, 2, 0);
722 auto gammaNode = GammaNode::create(&control0, 2);
723 auto entryVar1 = gammaNode->AddEntryVar(loopVar1.pre);
724 auto entryVar2 = gammaNode->AddEntryVar(loopVar2.pre);
726 gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar2.branchArgument[1] }).output;
728 auto user1 = TestOperation::createNode(&thetaRegion, { gammaOutput }, {});
730 auto & constant6 = BitConstantOperation::create(thetaRegion, { 32, 6 });
731 auto & constant7 = BitConstantOperation::create(thetaRegion, { 32, 7 });
732 loopVar1.post->divert_to(&constant6);
733 loopVar2.post->divert_to(&constant7);
740 const auto & user1Origin = *user1->input(0)->origin();
741 EXPECT_EQ(TryGetOwnerNode<GammaNode>(user1Origin), gammaNode);
TEST(CommonNodeEliminationTests, test_simple)
static jlm::util::StatisticsCollector statisticsCollector
Common Node Elimination Discovers simple nodes, region arguments and structural node outputs that are...
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type >> argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type >> resultTypes)
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
static GraphExport & Create(Output &origin, std::string name)
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
rvsdg::Region * subregion() const noexcept
PhiNode::ContextVar AddContextVar(jlm::rvsdg::Output &origin)
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
void begin(rvsdg::Region *parent)
Represents the argument of a region.
static std::shared_ptr< const TestType > createValueType()
static ThetaNode * create(rvsdg::Region *parent)
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)