Jlm
DifferencePropagationTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 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/llvm/TestRvsdgs.hpp>
11 
12 TEST(DifferencePropagationTests, TestTracksDifferences)
13 {
14  using namespace jlm;
15  using namespace jlm::llvm::aa;
16 
17  // Arrange
19  rvsdg.InitializeTest();
20 
21  PointerObjectSet set;
22  auto r0 = set.CreateRegisterPointerObject(rvsdg.GetAllocaOutput(0));
23  auto r1 = set.CreateRegisterPointerObject(rvsdg.GetAllocaOutput(1));
24  auto a0 = set.CreateAllocaMemoryObject(rvsdg.GetAllocaNode(0), true);
25  auto a1 = set.CreateAllocaMemoryObject(rvsdg.GetAllocaNode(1), true);
26  auto a2 = set.CreateAllocaMemoryObject(rvsdg.GetAllocaNode(2), true);
27  auto a3 = set.CreateAllocaMemoryObject(rvsdg.GetAllocaNode(3), true);
28 
29  // Let r0 -> a0 and r0 -> a3 before difference tracking even begins
30  set.AddToPointsToSet(r0, a0);
31  set.AddToPointsToSet(r0, a3);
32 
33  // Act
34  DifferencePropagation differencePropagation(set);
35  differencePropagation.Initialize();
36 
37  // Assert
38  EXPECT_EQ(differencePropagation.GetNewPointees(r0), (util::HashSet{ a0, a3 }));
39 
40  // Act 2 - add another pointer/pointee relation: r1 -> a1
41  differencePropagation.AddToPointsToSet(r1, a1);
42 
43  // Assert that a1 is a new pointee of r1
44  EXPECT_EQ(differencePropagation.GetNewPointees(r1), util::HashSet{ a1 });
45 
46  // Act 3 - clear difference tracking for r1
47  differencePropagation.ClearNewPointees(r1);
48 
49  // Assert r1 no longer has any new pointees
50  EXPECT_TRUE(differencePropagation.GetNewPointees(r1).IsEmpty());
51  // r0 still has new pointees
52  EXPECT_FALSE(differencePropagation.GetNewPointees(r0).IsEmpty());
53 
54  // Act 4 - add more pointees to r1,
55  bool new0 = differencePropagation.AddToPointsToSet(r1, a0);
56  bool new1 = differencePropagation.AddToPointsToSet(r1, a1); // not a new pointee
57  bool new2 = differencePropagation.AddToPointsToSet(r1, a2);
58 
59  // Assert that only a0 and a2 were new
60  EXPECT_TRUE(new0 && !new1 && new2);
61  EXPECT_EQ(differencePropagation.GetNewPointees(r1), util::HashSet({ a0, a2 }));
62 
63  // Act 5 - make r0 point to a superset of r1, making r0 now point to a0, a1, a2, a3
64  // First mark the existing pointees of r0 (a0 and a3) as seen
65  differencePropagation.ClearNewPointees(r0);
66  differencePropagation.MakePointsToSetSuperset(r0, r1);
67 
68  // Assert that only a1 and a2 are new to r0, as it has already marked a0 and a3 as seen
69  EXPECT_EQ(differencePropagation.GetNewPointees(r0), util::HashSet({ a1, a2 }));
70 
71  // Act 6 - give nodes r0 and r1 flags
72  set.MarkAsPointeesEscaping(r0);
74 
75  // Assert that the flags are new, but only if they actually have the flag
76  EXPECT_TRUE(differencePropagation.PointeesEscapeIsNew(r0));
77  EXPECT_FALSE(differencePropagation.PointsToExternalIsNew(r0));
78  EXPECT_FALSE(differencePropagation.PointeesEscapeIsNew(r1));
79  EXPECT_TRUE(differencePropagation.PointsToExternalIsNew(r1));
80 
81  // Act 7 - mark flags as seen
82  differencePropagation.MarkPointeesEscapeAsHandled(r0);
83  differencePropagation.MarkPointsToExternalAsHandled(r1);
84 
85  // Assert that the flags are no longer new
86  EXPECT_FALSE(differencePropagation.PointeesEscapeIsNew(r0));
87  EXPECT_FALSE(differencePropagation.PointsToExternalIsNew(r1));
88 
89  // Act 6 - unify 0 and 1
90  // After unification, any pointee or flag that is new to either node becomes new to the union
91  auto root = set.UnifyPointerObjects(r0, r1);
92  auto nonRoot = r0 + r1 - root;
93  differencePropagation.OnPointerObjectsUnified(root, nonRoot);
94 
95  // Assert that all pointees that were new to either node, are also new to the root
96  // a0 and a2 were still marked as new to node r1 at the time of unification.
97  // a3 is not new to r0, but r1 has never seen it, so it must be regarded as new by the union.
98  util::HashSet<PointerObjectIndex> subset{ a0, a2, a3 };
99  EXPECT_TRUE(subset.IsSubsetOf(differencePropagation.GetNewPointees(root)));
100 
101  // Neither flag has been seen by both nodes, so they are both new to the unification
102  EXPECT_TRUE(differencePropagation.PointeesEscapeIsNew(root));
103  EXPECT_TRUE(differencePropagation.PointsToExternalIsNew(root));
104 }
TEST(DifferencePropagationTests, TestTracksDifferences)
RVSDG module with an arbitrary amount of alloca nodes.
const rvsdg::SimpleNode & GetAllocaNode(size_t index) const noexcept
const jlm::rvsdg::Output & GetAllocaOutput(size_t index) const noexcept
bool AddToPointsToSet(PointerObjectIndex pointer, PointerObjectIndex pointee)
bool PointeesEscapeIsNew(PointerObjectIndex index)
void OnPointerObjectsUnified(PointerObjectIndex root, PointerObjectIndex nonRoot)
bool PointsToExternalIsNew(PointerObjectIndex index)
void MarkPointsToExternalAsHandled(PointerObjectIndex index)
const util::HashSet< PointerObjectIndex > & GetNewPointees(PointerObjectIndex index) const
bool MakePointsToSetSuperset(PointerObjectIndex superset, PointerObjectIndex subset)
void MarkPointeesEscapeAsHandled(PointerObjectIndex index)
void ClearNewPointees(PointerObjectIndex index)
PointerObjectIndex UnifyPointerObjects(PointerObjectIndex object1, PointerObjectIndex object2)
PointerObjectIndex CreateRegisterPointerObject(const rvsdg::Output &rvsdgOutput)
bool AddToPointsToSet(PointerObjectIndex pointer, PointerObjectIndex pointee)
bool MarkAsPointeesEscaping(PointerObjectIndex index)
PointerObjectIndex CreateAllocaMemoryObject(const rvsdg::SimpleNode &allocaNode, bool canPoint)
bool MarkAsPointingToExternal(PointerObjectIndex index)
bool IsEmpty() const noexcept
Definition: HashSet.hpp:198