6#include <gtest/gtest.h>
17 return haystack.find(needle) != std::string::npos;
21TEST(PointerObjectSetTests, TestFlagFunctions)
31 EXPECT_TRUE(set.
CanPoint(registerPO));
68TEST(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));
141TEST(PointerObjectSetTests, TestPointerObjectUnification)
155 EXPECT_NE((root == dummy0), (root == dummy1));
161 auto notRoot = dummy0 + dummy1 - root;
174TEST(PointerObjectSetTests, TestPointerObjectUnificationPointees)
219TEST(PointerObjectSetTests, TestAddToPointsToSet)
241TEST(PointerObjectSetTests, TestMakePointsToSetSuperset)
275TEST(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));
322TEST(PointerObjectSetTests, TestSupersetConstraint)
343 EXPECT_TRUE(
c1.ApplyDirectly(set));
344 while (
c1.ApplyDirectly(set))
352 EXPECT_TRUE(
c2.ApplyDirectly(set));
353 while (
c2.ApplyDirectly(set))
359 EXPECT_TRUE(
c1.ApplyDirectly(set));
360 while (
c1.ApplyDirectly(set))
368 EXPECT_TRUE(
c2.ApplyDirectly(set));
369 while (
c2.ApplyDirectly(set))
371 EXPECT_TRUE(
c1.ApplyDirectly(set));
372 while (
c1.ApplyDirectly(set))
379TEST(PointerObjectSetTests, TestStoreConstraintDirectly)
400 EXPECT_FALSE(
c1.ApplyDirectly(set));
405 EXPECT_TRUE(
c2.ApplyDirectly(set));
406 while (
c2.ApplyDirectly(set))
412 EXPECT_TRUE(
c1.ApplyDirectly(set));
413 while (
c1.ApplyDirectly(set))
419TEST(PointerObjectSetTests, TestLoadConstraintDirectly)
441 EXPECT_FALSE(
c1.ApplyDirectly(set));
446 EXPECT_TRUE(
c1.ApplyDirectly(set));
447 while (
c1.ApplyDirectly(set))
453TEST(PointerObjectSetTests, TestEscapedFunctionConstraint)
463 const auto & exportedFunctionReturn = *exportedFunction.
GetFunctionResults()[0]->origin();
474 bool result = EscapedFunctionConstraint::PropagateEscapedFunctionsDirectly(set);
477 EXPECT_FALSE(result);
478 EXPECT_FALSE(set.
HasEscaped(localFunctionRegisterPO));
479 EXPECT_FALSE(set.
HasEscaped(exportedFunctionPO));
484 result = EscapedFunctionConstraint::PropagateEscapedFunctionsDirectly(set);
488 result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
494TEST(PointerObjectSetTests, TestStoredAsScalarFlag)
511 bool result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
512 EXPECT_FALSE(result);
515 result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
546 result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
547 EXPECT_FALSE(result);
550TEST(PointerObjectSetTests, TestLoadedAsScalarFlag)
571 bool result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
572 EXPECT_FALSE(result);
575 result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
606 result = EscapeFlagConstraint::PropagateEscapedFlagsDirectly(set);
607 EXPECT_FALSE(result);
610TEST(PointerObjectSetTests, TestFunctionCallConstraint)
620 const auto lambdaFArgumentX =
622 const auto lambdaFArgumentY =
646TEST(PointerObjectSetTests, TestAddPointsToExternalConstraint)
688TEST(PointerObjectSetTests, TestAddRegisterContentEscapedConstraint)
722TEST(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(),
"{+}"));
771 EXPECT_TRUE(
StringContains(graph.GetNode(allocaReg0).GetLabel(), strfmt(
"{", alloca0,
"}")));
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)
875 if constexpr (solver == Andersen::Configuration::Solver::Worklist)
879 else if constexpr (solver == Andersen::Configuration::Solver::Naive)
881 static_assert(
sizeof...(args) == 0,
"The naive solver takes no arguments");
941TEST(PointerObjectSetTests, TestPointerObjectConstraintSetSolveNaive)
944 TestPointerObjectConstraintSetSolve<Configuration::Solver::Naive>();
947TEST(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());
972TEST(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 & GetMallocNode() const noexcept
const jlm::rvsdg::DeltaNode & GetDeltaNode() const noexcept
const rvsdg::SimpleNode & GetAllocaNode() const noexcept
const rvsdg::Output & GetDeltaOutput() const noexcept
const jlm::rvsdg::Output & GetAllocaOutput() const noexcept
const llvm::LlvmGraphImport & GetImportOutput() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaNode() 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::Output & GetLocalFunctionRegister() const noexcept
const jlm::rvsdg::LambdaNode & GetLocalFunction() 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()
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
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