Jlm
LazyCycleDetectionTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023, 2024 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
10 #include <jlm/util/HashSet.hpp>
11 
12 #include <cassert>
13 #include <vector>
14 
15 TEST(LazyCycleDetectionTests, TestUnifiesCycles)
16 {
17  using namespace jlm;
18  using namespace jlm::llvm::aa;
19 
20  // Arrange
21  PointerObjectSet set;
22  for (int i = 0; i < 6; i++)
23  {
25  }
26 
27  // Create a graph that looks like
28  // --> 1 --> 2 --> 3
29  // / |
30  // 0 |
31  // \ V
32  // --> 5 --> 4
33  std::vector<util::HashSet<PointerObjectIndex>> successors(set.NumPointerObjects());
34  successors[0].insert(1);
35  successors[1].insert(2);
36  successors[2].insert(3);
37  successors[2].insert(4);
38  successors[0].insert(5);
39  successors[5].insert(4);
40 
41  auto GetSuccessors = [&](PointerObjectIndex i)
42  {
43  EXPECT_TRUE(set.IsUnificationRoot(i));
44  return successors[i].Items();
45  };
46 
47  auto UnifyPointerObjects = [&](PointerObjectIndex a, PointerObjectIndex b)
48  {
49  EXPECT_TRUE(set.IsUnificationRoot(a));
50  EXPECT_TRUE(set.IsUnificationRoot(b));
51  EXPECT_NE(a, b);
52  auto newRoot = set.UnifyPointerObjects(a, b);
53  auto notRoot = a + b - newRoot;
54 
55  successors[newRoot].UnionWith(successors[notRoot]);
56  return newRoot;
57  };
58 
59  LazyCycleDetector lcd(set, GetSuccessors, UnifyPointerObjects);
60  lcd.Initialize();
61 
62  // Act 1 - an edge that is not a part of a cycle
63  lcd.OnPropagatedNothing(0, 1);
64 
65  // Assert that nothing happened
66  EXPECT_EQ(lcd.NumCycleDetectionAttempts(), 1u);
67  EXPECT_EQ(lcd.NumCyclesDetected(), 0u);
68  EXPECT_EQ(lcd.NumCycleUnifications(), 0u);
69 
70  // Act 2 - Try the same edge again
71  lcd.OnPropagatedNothing(0, 1);
72 
73  // Assert that the second attempt is ignored
74  EXPECT_EQ(lcd.NumCycleDetectionAttempts(), 1u);
75  EXPECT_EQ(lcd.NumCyclesDetected(), 0u);
76  EXPECT_EQ(lcd.NumCycleUnifications(), 0u);
77 
78  // Act 3 - add the edge 3->1 that creates a cycle 3-1-2-3
79  successors[3].insert(1);
80  lcd.OnPropagatedNothing(3, 1);
81 
82  // Assert that the cycle was found and unified
83  EXPECT_EQ(lcd.NumCycleDetectionAttempts(), 2u);
84  EXPECT_EQ(lcd.NumCyclesDetected(), 1u);
85  EXPECT_EQ(lcd.NumCycleUnifications(), 2u);
86  EXPECT_EQ(set.GetUnificationRoot(1), set.GetUnificationRoot(2));
87  EXPECT_EQ(set.GetUnificationRoot(1), set.GetUnificationRoot(3));
88 
89  // Act 4 - add the edge 4 -> 0, creating two cycles 4-0-5-4 and 4-0-(1/2/3)-4
90  successors[4].insert(0);
91  lcd.OnPropagatedNothing(4, 0);
92 
93  // Assert that both cycles were found.
94  // They are only counted as one cycle, but everything should be unified now
95  EXPECT_EQ(lcd.NumCyclesDetected(), 2u);
96  EXPECT_EQ(lcd.NumCycleUnifications(), set.NumPointerObjects() - 1);
97  for (PointerObjectIndex i = 1; i < set.NumPointerObjects(); i++)
98  {
99  EXPECT_EQ(set.GetUnificationRoot(0), set.GetUnificationRoot(i));
100  }
101 }
TEST(LazyCycleDetectionTests, TestUnifiesCycles)
size_t NumCycleUnifications() const noexcept
size_t NumCyclesDetected() const noexcept
size_t NumCycleDetectionAttempts() const noexcept
std::optional< PointerObjectIndex > OnPropagatedNothing(PointerObjectIndex subset, PointerObjectIndex superset)
PointerObjectIndex UnifyPointerObjects(PointerObjectIndex object1, PointerObjectIndex object2)
PointerObjectIndex CreateDummyRegisterPointerObject()
PointerObjectIndex GetUnificationRoot(PointerObjectIndex index) const noexcept
bool IsUnificationRoot(PointerObjectIndex index) const noexcept
size_t NumPointerObjects() const noexcept
uint32_t PointerObjectIndex