6 #include <gtest/gtest.h>
17 return haystack.find(needle) != std::string::npos;
21 TEST(PointerObjectSetTests, TestFlagFunctions)
31 EXPECT_TRUE(set.
CanPoint(registerPO));
68 TEST(PointerObjectSetTests, TestCreatePointerObjects)
111 EXPECT_FALSE(set.
CanPoint(alloca0));
115 EXPECT_TRUE(set.
CanPoint(register0));
116 EXPECT_FALSE(set.
CanPoint(lambda0));
117 EXPECT_FALSE(set.
CanPoint(import0));
141 TEST(PointerObjectSetTests, TestPointerObjectUnification)
155 EXPECT_NE((root == dummy0), (root == dummy1));
161 auto notRoot = dummy0 + dummy1 - root;
174 TEST(PointerObjectSetTests, TestPointerObjectUnificationPointees)
219 TEST(PointerObjectSetTests, TestAddToPointsToSet)
241 TEST(PointerObjectSetTests, TestMakePointsToSetSuperset)
275 TEST(PointerObjectSetTests, TestClonePointerObjectSet)
293 auto clonedSet = set.
Clone();
298 EXPECT_EQ(clonedSet->GetAllocaMap(), set.
GetAllocaMap());
299 EXPECT_EQ(clonedSet->GetMallocMap(), set.
GetMallocMap());
300 EXPECT_EQ(clonedSet->GetGlobalMap(), set.
GetGlobalMap());
302 EXPECT_EQ(clonedSet->GetImportMap(), set.
GetImportMap());
305 EXPECT_EQ(clonedSet->GetPointsToSet(register0), set.
GetPointsToSet(register0));
308 EXPECT_EQ(clonedSet->GetUnificationRoot(delta0), clonedSet->GetUnificationRoot(import0));
312 EXPECT_FALSE(clonedSet->GetPointsToSet(register0).Contains(lambda0));
314 clonedSet->UnifyPointerObjects(delta0, dummy0);
318 EXPECT_FALSE(clonedSet->IsPointingToExternal(malloc0));
322 TEST(PointerObjectSetTests, TestSupersetConstraint)
379 TEST(PointerObjectSetTests, TestStoreConstraintDirectly)
419 TEST(PointerObjectSetTests, TestLoadConstraintDirectly)
453 TEST(PointerObjectSetTests, TestEscapedFunctionConstraint)
463 const auto & exportedFunctionReturn = *exportedFunction.
GetFunctionResults()[0]->origin();
477 EXPECT_FALSE(result);
478 EXPECT_FALSE(set.
HasEscaped(localFunctionRegisterPO));
479 EXPECT_FALSE(set.
HasEscaped(exportedFunctionPO));
494 TEST(PointerObjectSetTests, TestStoredAsScalarFlag)
512 EXPECT_FALSE(result);
547 EXPECT_FALSE(result);
550 TEST(PointerObjectSetTests, TestLoadedAsScalarFlag)
572 EXPECT_FALSE(result);
607 EXPECT_FALSE(result);
610 TEST(PointerObjectSetTests, TestFunctionCallConstraint)
620 const auto lambdaFArgumentX =
622 const auto lambdaFArgumentY =
646 TEST(PointerObjectSetTests, TestAddPointsToExternalConstraint)
688 TEST(PointerObjectSetTests, TestAddRegisterContentEscapedConstraint)
722 TEST(PointerObjectSetTests, TestDrawSubsetGraph)
737 const auto nonRoot = dummy0 + dummy1 - root;
765 EXPECT_TRUE(
StringContains(graph.GetNode(nonRoot).GetLabel(),
"#" + std::to_string(root)));
768 EXPECT_TRUE(
StringContains(graph.GetNode(root).GetLabel(),
"{+}"));
774 auto * supersetEdge = graph.GetEdgeBetween(graph.GetNode(allocaReg0), graph.GetNode(import0));
775 EXPECT_TRUE(supersetEdge);
776 EXPECT_TRUE(supersetEdge->IsDirected());
777 EXPECT_EQ(supersetEdge->GetAttributeString(
"style").value_or(
"solid"),
"solid");
780 auto * storeEdge = graph.GetEdgeBetween(graph.GetNode(storeValue), graph.GetNode(storePointer));
781 EXPECT_TRUE(storeEdge);
782 EXPECT_TRUE(storeEdge->IsDirected());
783 EXPECT_TRUE(storeEdge->GetAttributeString(
"style") == graph::Edge::Style::Dashed);
784 EXPECT_TRUE(
StringContains(storeEdge->GetAttributeString(
"arrowhead").value(),
"dot"));
787 auto * loadEdge = graph.GetEdgeBetween(graph.GetNode(loadPointer), graph.GetNode(loadValue));
788 EXPECT_TRUE(loadEdge);
789 EXPECT_TRUE(loadEdge->IsDirected());
790 EXPECT_TRUE(loadEdge->GetAttributeString(
"style") == graph::Edge::Style::Dashed);
791 EXPECT_TRUE(
StringContains(loadEdge->GetAttributeString(
"arrowtail").value(),
"dot"));
794 auto & functionNode = graph.GetNode(function0);
795 EXPECT_TRUE(
StringContains(functionNode.GetLabel(),
"function0"));
797 EXPECT_TRUE(
StringContains(functionNode.GetLabel(),
"CantPoint"));
802 auto & importNode = graph.GetNode(import0);
803 EXPECT_TRUE(importNode.HasAttribute(
"fillcolor"));
819 for (
unsigned int & i : reg)
881 static_assert(
sizeof...(args) == 0,
"The naive solver takes no arguments");
941 TEST(PointerObjectSetTests, TestPointerObjectConstraintSetSolveNaive)
944 TestPointerObjectConstraintSetSolve<Configuration::Solver::Naive>();
947 TEST(PointerObjectSetTests, TestPointerObjectConstraintSetSolveWorklist)
952 for (
const auto & config : allConfigs)
957 if (config.IsOfflineVariableSubstitutionEnabled())
959 if (config.IsOfflineConstraintNormalizationEnabled())
962 TestPointerObjectConstraintSetSolve<Configuration::Solver::Worklist>(
963 config.GetWorklistSoliverPolicy(),
964 config.IsOnlineCycleDetectionEnabled(),
965 config.IsHybridCycleDetectionEnabled(),
966 config.IsLazyCycleDetectionEnabled(),
967 config.IsDifferencePropagationEnabled(),
968 config.IsPreferImplicitPointeesEnabled());
972 TEST(PointerObjectSetTests, TestClonePointerObjectConstraintSet)
990 auto [setClone, constraintsClone] = constraints.
Clone();
993 constraintsClone->AddConstraint(
LoadConstraint(register0, alloca0));
994 EXPECT_EQ(constraintsClone->GetConstraints().size(), 2u);
1000 EXPECT_TRUE(setClone->GetPointsToSet(dummy0).IsEmpty());
1002 constraintsClone->SolveNaively();
1003 EXPECT_TRUE(setClone->GetPointsToSet(dummy0).Contains(alloca0));
static void TestPointerObjectConstraintSetSolve(Args... args)
static bool StringContains(std::string_view haystack, std::string_view needle)
TEST(PointerObjectSetTests, TestFlagFunctions)
RVSDG module with one of each memory node type.
const rvsdg::SimpleNode & GetAllocaNode() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNode() const noexcept
const jlm::rvsdg::Output & GetAllocaOutput() const noexcept
const rvsdg::Output & GetDeltaOutput() const noexcept
const llvm::LlvmGraphImport & GetImportOutput() const noexcept
const rvsdg::SimpleNode & GetMallocNode() const noexcept
const jlm::rvsdg::DeltaNode & GetDeltaNode() const noexcept
rvsdg::SimpleNode * alloca_y
jlm::rvsdg::LambdaNode * lambda_f
rvsdg::SimpleNode * alloca_x
const rvsdg::SimpleNode & CallF() const noexcept
RVSDG module with a static function escaping through another function.
const jlm::rvsdg::LambdaNode & GetExportedFunction() const noexcept
const jlm::rvsdg::LambdaNode & GetLocalFunction() const noexcept
const jlm::rvsdg::Output & GetLocalFunctionRegister() const noexcept
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
static std::vector< Configuration > GetAllConfigurations()
static bool PropagateEscapedFlagsDirectly(PointerObjectSet &set)
static bool PropagateEscapedFunctionsDirectly(PointerObjectSet &set)
bool ApplyDirectly(PointerObjectSet &set)
bool ApplyDirectly(PointerObjectSet &set)
void AddPointerPointeeConstraint(PointerObjectIndex pointer, PointerObjectIndex pointee)
util::graph::Graph & DrawSubsetGraph(util::graph::Writer &writer) const
std::pair< std::unique_ptr< PointerObjectSet >, std::unique_ptr< PointerObjectConstraintSet > > Clone() const
void AddConstraint(ConstraintVariant c)
WorklistStatistics SolveUsingWorklist(WorklistSolverPolicy policy, bool enableOnlineCycleDetection, bool enableHybridCycleDetection, bool enableLazyCycleDetection, bool enableDifferencePropagation, bool enablePreferImplicitPropation)
const std::vector< ConstraintVariant > & GetConstraints() const noexcept
void AddPointsToExternalConstraint(PointerObjectIndex pointer)
void AddRegisterContentEscapedConstraint(PointerObjectIndex registerIndex)
const util::BijectiveMap< const rvsdg::LambdaNode *, PointerObjectIndex > & GetFunctionMap() const noexcept
PointerObjectIndex CreateMallocMemoryObject(const rvsdg::SimpleNode &mallocNode, bool canPoint)
PointerObjectIndex UnifyPointerObjects(PointerObjectIndex object1, PointerObjectIndex object2)
bool IsPointingTo(PointerObjectIndex pointer, PointerObjectIndex pointee) const
PointerObjectIndex CreateDummyRegisterPointerObject()
PointerObjectKind GetPointerObjectKind(PointerObjectIndex index) const noexcept
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetMallocMap() const noexcept
bool IsPointerObjectRegister(PointerObjectIndex index) const noexcept
PointerObjectIndex CreateGlobalMemoryObject(const rvsdg::DeltaNode &deltaNode, bool canPoint)
void MapRegisterToExistingPointerObject(const rvsdg::Output &rvsdgOutput, PointerObjectIndex pointerObject)
const util::HashSet< PointerObjectIndex > & GetPointsToSet(PointerObjectIndex index) const
bool HasPointeesEscaping(PointerObjectIndex index) const noexcept
bool IsLoadedAsScalar(PointerObjectIndex index) const noexcept
PointerObjectIndex CreateRegisterPointerObject(const rvsdg::Output &rvsdgOutput)
bool CanPoint(PointerObjectIndex index) const noexcept
bool AddToPointsToSet(PointerObjectIndex pointer, PointerObjectIndex pointee)
PointerObjectIndex GetRegisterPointerObject(const rvsdg::Output &rvsdgOutput) const
bool MarkAsLoadingAsScalar(PointerObjectIndex index)
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetAllocaMap() const noexcept
std::unique_ptr< PointerObjectSet > Clone() const
bool IsPointingToExternal(PointerObjectIndex index) const noexcept
bool IsStoredAsScalar(PointerObjectIndex index) const noexcept
bool HasEscaped(PointerObjectIndex index) const noexcept
bool MarkAsPointeesEscaping(PointerObjectIndex index)
const std::unordered_map< const LlvmGraphImport *, PointerObjectIndex > & GetImportMap() const noexcept
const std::unordered_map< const rvsdg::DeltaNode *, PointerObjectIndex > & GetGlobalMap() const noexcept
PointerObjectIndex CreateAllocaMemoryObject(const rvsdg::SimpleNode &allocaNode, bool canPoint)
bool MarkAsStoringAsScalar(PointerObjectIndex index)
bool MarkAsPointingToExternal(PointerObjectIndex index)
PointerObjectIndex GetUnificationRoot(PointerObjectIndex index) const noexcept
bool IsUnificationRoot(PointerObjectIndex index) const noexcept
PointerObjectIndex CreateFunctionMemoryObject(const rvsdg::LambdaNode &lambdaNode)
size_t NumPointerObjects() const noexcept
const rvsdg::LambdaNode & GetLambdaNodeFromFunctionMemoryObject(PointerObjectIndex index) const
const std::unordered_map< const rvsdg::Output *, PointerObjectIndex > & GetRegisterMap() const noexcept
PointerObjectIndex CreateImportMemoryObject(const LlvmGraphImport &importNode, bool canPoint)
bool MarkAsEscaped(PointerObjectIndex index)
PointerObjectIndex GetFunctionMemoryObject(const rvsdg::LambdaNode &lambdaNode) const
bool MakePointsToSetSuperset(PointerObjectIndex superset, PointerObjectIndex subset)
std::optional< PointerObjectIndex > TryGetRegisterPointerObject(const rvsdg::Output &rvsdgOutput) const
size_t NumPointerObjectsOfKind(PointerObjectKind kind) const noexcept
bool ApplyDirectly(PointerObjectSet &set)
bool ApplyDirectly(PointerObjectSet &set)
std::vector< rvsdg::Output * > GetFunctionArguments() const
std::vector< rvsdg::Input * > GetFunctionResults() const
rvsdg::Output * output() const noexcept
NodeOutput * output(size_t index) const noexcept
std::size_t Size() const noexcept
bool Contains(const ItemType &item) const noexcept
#define JLM_UNREACHABLE(msg)
uint32_t PointerObjectIndex
static std::string strfmt(Args... args)