Jlm
CommonNodeEliminationTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
12 #include <jlm/rvsdg/control.hpp>
13 #include <jlm/rvsdg/gamma.hpp>
14 #include <jlm/rvsdg/Phi.hpp>
16 #include <jlm/rvsdg/TestType.hpp>
17 #include <jlm/rvsdg/theta.hpp>
18 #include <jlm/rvsdg/view.hpp>
19 #include <jlm/util/Statistics.hpp>
20 
22 
23 TEST(CommonNodeEliminationTests, test_simple)
24 {
25  using namespace jlm::llvm;
26  using namespace jlm::rvsdg;
27 
29 
31  auto & graph = rm.Rvsdg();
32 
33  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
34  auto y = &jlm::rvsdg::GraphImport::Create(graph, vt, "y");
35  auto z = &jlm::rvsdg::GraphImport::Create(graph, vt, "z");
36 
37  auto n1 = TestOperation::createNode(&graph.GetRootRegion(), {}, { vt })->output(0);
38  auto n2 = TestOperation::createNode(&graph.GetRootRegion(), {}, { vt })->output(0);
39 
40  auto u1 = TestOperation::createNode(&graph.GetRootRegion(), { z }, { vt })->output(0);
41 
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);
46 
54 
55  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
57  cne.Run(rm, statisticsCollector);
58  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
59 
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());
63 }
64 
65 TEST(CommonNodeEliminationTests, test_gamma)
66 {
67  using namespace jlm::llvm;
68  using namespace jlm::rvsdg;
69 
72 
74  auto & graph = rm.Rvsdg();
75 
76  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
77  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
78  auto y = &jlm::rvsdg::GraphImport::Create(graph, vt, "y");
79  auto z = &jlm::rvsdg::GraphImport::Create(graph, vt, "z");
80 
81  auto u1 = TestOperation::createNode(&graph.GetRootRegion(), { x }, { vt })->output(0);
82  auto u2 = TestOperation::createNode(&graph.GetRootRegion(), { x }, { vt })->output(0);
83 
84  auto gamma = jlm::rvsdg::GammaNode::create(c, 2);
85 
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);
91 
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);
95 
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] });
103 
104  jlm::rvsdg::GraphExport::Create(*gamma->output(0), "x1");
105  jlm::rvsdg::GraphExport::Create(*gamma->output(1), "x2");
106  jlm::rvsdg::GraphExport::Create(*gamma->output(2), "y");
107 
108  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
110  cne.Run(rm, statisticsCollector);
111  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
112 
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());
121 
122  auto argument0 =
123  dynamic_cast<const jlm::rvsdg::RegionArgument *>(subregion0->result(6)->origin());
124  auto argument1 =
125  dynamic_cast<const jlm::rvsdg::RegionArgument *>(subregion1->result(6)->origin());
126  EXPECT_EQ(argument0->input(), argument1->input());
127 }
128 
129 TEST(CommonNodeEliminationTests, test_gamma_congruent_exit_vars)
130 {
131  using namespace jlm::llvm;
132  using namespace jlm::rvsdg;
133 
157  // Arrange
159  auto ct = jlm::rvsdg::ControlType::Create(2);
160 
162  auto & graph = rm.Rvsdg();
163 
164  auto importPredicate = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
165  auto importA = &jlm::rvsdg::GraphImport::Create(graph, vt, "a");
166  auto importB = &jlm::rvsdg::GraphImport::Create(graph, vt, "b");
167 
168  auto gamma = jlm::rvsdg::GammaNode::create(importPredicate, 2);
169 
170  auto entryVarA = gamma->AddEntryVar(importA);
171  auto entryVarB = gamma->AddEntryVar(importB);
172 
173  // Create invariant exit variables that simply copy the inputs
174  auto exitVarA = gamma->AddExitVar({ entryVarA.branchArgument[0], entryVarA.branchArgument[1] });
175  auto exitVarB = gamma->AddExitVar({ entryVarB.branchArgument[0], entryVarB.branchArgument[1] });
176 
177  // Create exit variables that mix between different inputs
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] });
181 
182  auto & exportA = jlm::rvsdg::GraphExport::Create(*exitVarA.output, "a2");
183  auto & exportB = jlm::rvsdg::GraphExport::Create(*exitVarB.output, "b2");
184  auto & exportX = jlm::rvsdg::GraphExport::Create(*exitVarX.output, "x");
185  auto & exportY = jlm::rvsdg::GraphExport::Create(*exitVarY.output, "y");
186  auto & exportZ = jlm::rvsdg::GraphExport::Create(*exitVarZ.output, "z");
187 
188  // Act
190  cne.Run(rm, statisticsCollector);
191 
192  // Assert
193 
194  // The invariant gamma outputs have been routed around the gamma
195  EXPECT_EQ(exportA.origin(), importA);
196  EXPECT_EQ(exportB.origin(), importB);
197 
198  // "x" and "y" are identical, so they should have a single origin (exit var X)
199  EXPECT_EQ(exportX.origin(), exitVarX.output);
200  EXPECT_EQ(exportY.origin(), exitVarX.output);
201  EXPECT_EQ(exitVarY.output->nusers(), 0u);
202 
203  // "z" should remain untouced
204  EXPECT_EQ(exportZ.origin(), exitVarZ.output);
205 }
206 
207 TEST(CommonNodeEliminationTests, test_theta)
208 {
209  using namespace jlm::llvm;
210  using namespace jlm::rvsdg;
211 
213  auto ct = jlm::rvsdg::ControlType::Create(2);
214 
216  auto & graph = rm.Rvsdg();
217 
218  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
219  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
220 
221  auto theta = jlm::rvsdg::ThetaNode::create(&graph.GetRootRegion());
222  auto region = theta->subregion();
223 
224  auto lv1 = theta->AddLoopVar(c);
225  auto lv2 = theta->AddLoopVar(x);
226  auto lv3 = theta->AddLoopVar(x);
227  auto lv4 = theta->AddLoopVar(x);
228 
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);
232 
233  lv2.post->divert_to(u1);
234  lv3.post->divert_to(u2);
235  lv4.post->divert_to(b1);
236 
237  theta->set_predicate(lv1.pre);
238 
239  jlm::rvsdg::GraphExport::Create(*lv2.output, "lv2");
240  jlm::rvsdg::GraphExport::Create(*lv3.output, "lv3");
241  jlm::rvsdg::GraphExport::Create(*lv4.output, "lv4");
242 
243  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
245  cne.Run(rm, statisticsCollector);
246  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
247 
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());
256 }
257 
258 TEST(CommonNodeEliminationTests, test_theta2)
259 {
260  using namespace jlm::llvm;
261  using namespace jlm::rvsdg;
262 
264  auto ct = jlm::rvsdg::ControlType::Create(2);
265 
267  auto & graph = rm.Rvsdg();
268 
269  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
270  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
271 
272  auto theta = jlm::rvsdg::ThetaNode::create(&graph.GetRootRegion());
273  auto region = theta->subregion();
274 
275  auto lv1 = theta->AddLoopVar(c);
276  auto lv2 = theta->AddLoopVar(x);
277  auto lv3 = theta->AddLoopVar(x);
278 
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);
282 
283  lv2.post->divert_to(u1);
284  lv3.post->divert_to(b1);
285 
286  theta->set_predicate(lv1.pre);
287 
288  jlm::rvsdg::GraphExport::Create(*lv2.output, "lv2");
289  jlm::rvsdg::GraphExport::Create(*lv3.output, "lv3");
290 
291  // jlm::rvsdg::view(graph, stdout);
293  cne.Run(rm, statisticsCollector);
294  // jlm::rvsdg::view(graph, stdout);
295 
296  EXPECT_EQ(lv2.post->origin(), u1);
297  EXPECT_NE(lv2.pre->nusers(), 0u);
298  EXPECT_NE(lv3.pre->nusers(), 0u);
299 }
300 
301 TEST(CommonNodeEliminationTests, test_theta3)
302 {
303  using namespace jlm::llvm;
304  using namespace jlm::rvsdg;
305 
307  auto ct = jlm::rvsdg::ControlType::Create(2);
308 
310  auto & graph = rm.Rvsdg();
311 
312  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
313  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
314 
315  auto theta1 = jlm::rvsdg::ThetaNode::create(&graph.GetRootRegion());
316  auto r1 = theta1->subregion();
317 
318  auto lv1 = theta1->AddLoopVar(c);
319  auto lv2 = theta1->AddLoopVar(x);
320  auto lv3 = theta1->AddLoopVar(x);
321  auto lv4 = theta1->AddLoopVar(x);
322 
323  auto theta2 = jlm::rvsdg::ThetaNode::create(r1);
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);
330 
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 });
334 
335  lv2.post->divert_to(u1->output(0));
336  lv3.post->divert_to(b1->output(0));
337  lv4.post->divert_to(u1->output(0));
338 
339  theta1->set_predicate(lv1.pre);
340 
341  jlm::rvsdg::GraphExport::Create(*lv2.output, "lv2");
342  jlm::rvsdg::GraphExport::Create(*lv3.output, "lv3");
343  jlm::rvsdg::GraphExport::Create(*lv4.output, "lv4");
344 
345  // jlm::rvsdg::view(graph, stdout);
347  cne.Run(rm, statisticsCollector);
348  // jlm::rvsdg::view(graph, stdout);
349 
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());
356 }
357 
358 TEST(CommonNodeEliminationTests, test_theta4)
359 {
360  using namespace jlm::llvm;
361  using namespace jlm::rvsdg;
362 
364  auto ct = jlm::rvsdg::ControlType::Create(2);
365 
367  auto & graph = rm.Rvsdg();
368 
369  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
370  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
371  auto y = &jlm::rvsdg::GraphImport::Create(graph, vt, "y");
372 
373  auto theta = jlm::rvsdg::ThetaNode::create(&graph.GetRootRegion());
374  auto region = theta->subregion();
375 
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);
383 
384  auto u1 = TestOperation::createNode(region, { lv2.pre }, { vt });
385  auto b1 = TestOperation::createNode(region, { lv3.pre, lv3.pre }, { vt });
386 
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));
391 
392  theta->set_predicate(lv1.pre);
393 
394  auto & ex1 = jlm::rvsdg::GraphExport::Create(*theta->output(1), "lv2");
395  auto & ex2 = jlm::rvsdg::GraphExport::Create(*theta->output(2), "lv3");
396  jlm::rvsdg::GraphExport::Create(*theta->output(3), "lv4");
397  jlm::rvsdg::GraphExport::Create(*theta->output(4), "lv5");
398 
399  // jlm::rvsdg::view(graph, stdout);
401  cne.Run(rm, statisticsCollector);
402  // jlm::rvsdg::view(graph, stdout);
403 
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());
408 }
409 
410 TEST(CommonNodeEliminationTests, test_theta5)
411 {
412  using namespace jlm::llvm;
413 
415  auto ct = jlm::rvsdg::ControlType::Create(2);
416 
417  LlvmRvsdgModule rm(jlm::util::FilePath(""), "", "");
418  auto & graph = rm.Rvsdg();
419 
420  auto c = &jlm::rvsdg::GraphImport::Create(graph, ct, "c");
421  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
422  auto y = &jlm::rvsdg::GraphImport::Create(graph, vt, "y");
423 
424  auto theta = jlm::rvsdg::ThetaNode::create(&graph.GetRootRegion());
425  auto region = theta->subregion();
426 
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);
432 
433  lv1.post->divert_to(lv3.pre);
434  lv2.post->divert_to(lv4.pre);
435 
436  theta->set_predicate(lv0.pre);
437 
438  auto & ex1 = jlm::rvsdg::GraphExport::Create(*theta->output(1), "lv1");
439  auto & ex2 = jlm::rvsdg::GraphExport::Create(*theta->output(2), "lv2");
440  auto & ex3 = jlm::rvsdg::GraphExport::Create(*theta->output(3), "lv3");
441  auto & ex4 = jlm::rvsdg::GraphExport::Create(*theta->output(4), "lv4");
442 
443  // jlm::rvsdg::view(graph, stdout);
445  cne.Run(rm, statisticsCollector);
446  // jlm::rvsdg::view(graph, stdout);
447 
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());
452 }
453 
454 TEST(CommonNodeEliminationTests, MultipleThetas)
455 {
456  using namespace jlm::llvm;
457  using namespace jlm::rvsdg;
458 
459  // Arrange
460  const auto valueType = TestType::createValueType();
461 
462  jlm::llvm::LlvmRvsdgModule rvsdgModule(jlm::util::FilePath(""), "", "");
463  auto & rvsdg = rvsdgModule.Rvsdg();
464 
465  auto & i0 = jlm::rvsdg::GraphImport::Create(rvsdg, valueType, "i0");
466 
467  // Loop 1
468  auto thetaNode1 = ThetaNode::create(&rvsdg.GetRootRegion());
469  auto loopVariable1 = thetaNode1->AddLoopVar(&i0);
470  auto node1 =
471  TestOperation::createNode(thetaNode1->subregion(), { loopVariable1.pre }, { valueType });
472  loopVariable1.post->divert_to(node1->output(0));
473 
474  // Loop 2
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);
479  auto node2 =
480  TestOperation::createNode(thetaNode1->subregion(), { loopVariable2.pre }, { valueType });
481  loopVariable2.post->divert_to(node2->output(0));
482 
483  // Loop 3
484  auto thetaNode3 = ThetaNode::create(&rvsdg.GetRootRegion());
485  auto loopVariable3 = thetaNode3->AddLoopVar(loopVariable1.output);
486  auto loopVariable4 = thetaNode3->AddLoopVar(loopVariable2.output);
487 
488  auto & x1 = jlm::rvsdg::GraphExport::Create(*loopVariable3.output, "x1");
489  auto & x2 = jlm::rvsdg::GraphExport::Create(*loopVariable4.output, "x2");
490 
491  view(rvsdg, stdout);
492 
493  // Act
494  CommonNodeElimination commonNodeElimination;
495  commonNodeElimination.Run(rvsdgModule, statisticsCollector);
496 
497  view(rvsdg, stdout);
498 
499  // Assert
500  // The origins from x1 and x2 are ultimately from two different loops with different iteration
501  // counts. They are NOT congruent.
502  EXPECT_NE(x1.origin(), x2.origin());
503 }
504 
505 TEST(CommonNodeEliminationTests, MultipleThetasPassthrough)
506 {
507  using namespace jlm::llvm;
508  using namespace jlm::rvsdg;
509 
510  // Arrange
511  const auto valueType = TestType::createValueType();
512 
513  jlm::llvm::LlvmRvsdgModule rvsdgModule(jlm::util::FilePath(""), "", "");
514  auto & rvsdg = rvsdgModule.Rvsdg();
515 
516  auto & i0 = jlm::rvsdg::GraphImport::Create(rvsdg, valueType, "i0");
517 
518  // Loop 1
519  auto thetaNode1 = ThetaNode::create(&rvsdg.GetRootRegion());
520  auto loopVariable1 = thetaNode1->AddLoopVar(&i0);
521 
522  // Loop 2
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);
527 
528  // Loop 3
529  auto thetaNode3 = ThetaNode::create(&rvsdg.GetRootRegion());
530  auto loopVariable3 = thetaNode3->AddLoopVar(loopVariable1.output);
531  auto loopVariable4 = thetaNode3->AddLoopVar(loopVariable2.output);
532 
533  auto & x1 = jlm::rvsdg::GraphExport::Create(*loopVariable3.output, "x1");
534  auto & x2 = jlm::rvsdg::GraphExport::Create(*loopVariable4.output, "x2");
535 
536  view(rvsdg, stdout);
537 
538  // Act
539  CommonNodeElimination commonNodeElimination;
540  commonNodeElimination.Run(rvsdgModule, statisticsCollector);
541 
542  view(rvsdg, stdout);
543 
544  // Assert
545  // The origins from x1 and x2 are ultimately from two different loops with different iteration
546  // counts, BUT the values in these loops are only passthrough values. Thus, we would expect them
547  // to be congruent.
548  EXPECT_EQ(x1.origin(), x2.origin());
549 }
550 
551 TEST(CommonNodeEliminationTests, test_lambda)
552 {
553  using namespace jlm::llvm;
554  using namespace jlm::rvsdg;
555 
557  auto ft = jlm::rvsdg::FunctionType::Create({ vt, vt }, { vt });
558 
560  auto & graph = rm.Rvsdg();
561 
562  auto x = &jlm::rvsdg::GraphImport::Create(graph, vt, "x");
563 
564  auto lambda = jlm::rvsdg::LambdaNode::Create(
565  graph.GetRootRegion(),
567 
568  auto d1 = lambda->AddContextVar(*x).inner;
569  auto d2 = lambda->AddContextVar(*x).inner;
570 
571  auto b1 = TestOperation::createNode(lambda->subregion(), { d1, d2 }, { vt })->output(0);
572 
573  auto output = lambda->finalize({ b1 });
574 
575  jlm::rvsdg::GraphExport::Create(*output, "f");
576 
577  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
579  cne.Run(rm, statisticsCollector);
580  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
581 
582  auto bn1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*b1);
583  EXPECT_EQ(bn1->input(0)->origin(), bn1->input(1)->origin());
584 }
585 
586 TEST(CommonNodeEliminationTests, test_phi)
587 {
588  using namespace jlm::llvm;
589 
591  auto ft = jlm::rvsdg::FunctionType::Create({ vt, vt }, { vt });
592 
593  LlvmRvsdgModule rm(jlm::util::FilePath(""), "", "");
594  auto & graph = rm.Rvsdg();
595 
596  auto & x = jlm::rvsdg::GraphImport::Create(graph, vt, "x");
597 
599  pb.begin(&graph.GetRootRegion());
600  auto region = pb.subregion();
601 
602  auto d1 = pb.AddContextVar(x);
603  auto d2 = pb.AddContextVar(x);
604 
605  auto r1 = pb.AddFixVar(ft);
606  auto r2 = pb.AddFixVar(ft);
607 
608  auto lambda1 = jlm::rvsdg::LambdaNode::Create(
609  *region,
611  auto cv1 = lambda1->AddContextVar(*d1.inner).inner;
612  auto f1 = lambda1->finalize({ cv1 });
613 
614  auto lambda2 = jlm::rvsdg::LambdaNode::Create(
615  *region,
617  auto cv2 = lambda2->AddContextVar(*d2.inner).inner;
618  auto f2 = lambda2->finalize({ cv2 });
619 
620  r1.result->divert_to(f1);
621  r2.result->divert_to(f2);
622 
623  auto phi = pb.end();
624 
625  jlm::rvsdg::GraphExport::Create(*phi->output(0), "f1");
626  jlm::rvsdg::GraphExport::Create(*phi->output(1), "f2");
627 
628  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
630  cne.Run(rm, statisticsCollector);
631  // jlm::rvsdg::view(graph.GetRootRegion(), stdout);
632 
633  EXPECT_EQ(
634  jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*f1).input(0)->origin(),
635  jlm::rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*f2).input(0)->origin());
636 }
637 
638 TEST(CommonNodeEliminationTests, EmptyTheta)
639 {
640  using namespace jlm::llvm;
641  using namespace jlm::rvsdg;
642 
643  // Arrange
644  auto valueType = TestType::createValueType();
645  auto controlType = ControlType::Create(2);
646 
647  LlvmRvsdgModule rvsdgModule(jlm::util::FilePath(""), "", "");
648  auto & rvsdg = rvsdgModule.Rvsdg();
649 
650  auto thetaNode = ThetaNode::create(&rvsdg.GetRootRegion());
651 
652  auto node1 = TestOperation::createNode(thetaNode->subregion(), {}, { valueType });
653  auto node2 =
654  TestOperation::createNode(thetaNode->subregion(), { node1->output(0) }, { valueType });
655  auto node3 =
656  TestOperation::createNode(thetaNode->subregion(), { node1->output(0) }, { valueType });
657  auto node4 = TestOperation::createNode(
658  thetaNode->subregion(),
659  { node2->output(0), node3->output(0) },
660  { controlType });
661 
662  thetaNode->set_predicate(node4->output(0));
663 
664  view(rvsdg, stdout);
665 
666  // Act
667  CommonNodeElimination commonNodeElimination;
668  commonNodeElimination.Run(rvsdgModule, statisticsCollector);
669 
670  thetaNode->subregion()->prune(false);
671 
672  view(rvsdg, stdout);
673 
674  // Assert
675  // We expect that node2 and node3 are unified in the theta subregion
676  EXPECT_EQ(thetaNode->subregion()->numNodes(), 3u);
677 }
678 
679 TEST(CommonNodeEliminationTests, GammaInTheta)
680 {
705  using namespace jlm::llvm;
706  using namespace jlm::rvsdg;
707 
708  // Arrange
709  const auto valueType = TestType::createValueType();
710 
711  LlvmRvsdgModule rvsdgModule(jlm::util::FilePath(""), "", "");
712  auto & rvsdg = rvsdgModule.Rvsdg();
713 
714  auto & constant10 = BitConstantOperation::create(rvsdg.GetRootRegion(), { 32, 10 });
715 
716  auto thetaNode = ThetaNode::create(&rvsdg.GetRootRegion());
717  auto loopVar1 = thetaNode->AddLoopVar(&constant10);
718  auto loopVar2 = thetaNode->AddLoopVar(&constant10);
719  auto & thetaRegion = *thetaNode->subregion();
720 
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);
725  auto gammaOutput =
726  gammaNode->AddExitVar({ entryVar1.branchArgument[0], entryVar2.branchArgument[1] }).output;
727 
728  auto user1 = TestOperation::createNode(&thetaRegion, { gammaOutput }, {});
729 
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);
734 
735  // Act
736  CommonNodeElimination commonNodeElimination;
737  commonNodeElimination.Run(rvsdgModule, statisticsCollector);
738 
739  // Assert
740  const auto & user1Origin = *user1->input(0)->origin();
741  EXPECT_EQ(TryGetOwnerNode<GammaNode>(user1Origin), gammaNode);
742 }
TEST(CommonNodeEliminationTests, test_simple)
static jlm::util::StatisticsCollector statisticsCollector
static const auto vt
Definition: PullTests.cpp:16
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)
Definition: lambda.hpp:84
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
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)
Definition: gamma.hpp:161
static GraphExport & Create(Output &origin, std::string name)
Definition: graph.cpp:62
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Definition: graph.cpp:36
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
rvsdg::Region * subregion() const noexcept
Definition: Phi.hpp:349
PhiNode * end()
Definition: Phi.cpp:270
PhiNode::ContextVar AddContextVar(jlm::rvsdg::Output &origin)
Definition: Phi.cpp:251
PhiNode::FixVar AddFixVar(std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: Phi.cpp:257
void begin(rvsdg::Region *parent)
Definition: Phi.hpp:355
Represents the argument of a region.
Definition: region.hpp:41
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
static ThetaNode * create(rvsdg::Region *parent)
Definition: theta.hpp:73
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
Definition: view.cpp:142