53 for (
auto & pointerObject : PointerObjects_)
55 count += pointerObject.Kind == kind;
78 count += !pointerObject.IsRegister() && pointerObject.CanPoint();
98 std::optional<PointerObjectIndex>
151 return pointerObject;
178 return importMemoryObject;
181 const std::unordered_map<const rvsdg::Output *, PointerObjectIndex> &
187 const std::unordered_map<const rvsdg::SimpleNode *, PointerObjectIndex> &
193 const std::unordered_map<const rvsdg::SimpleNode *, PointerObjectIndex> &
199 const std::unordered_map<const rvsdg::DeltaNode *, PointerObjectIndex> &
211 const std::unordered_map<const LlvmGraphImport *, PointerObjectIndex> &
221 return PointerObjects_[index].Kind;
228 return PointerObjects_[index].CanPoint();
235 return PointerObjects_[index].IsRegister();
242 return PointerObjects_[index].HasEscaped;
265 return PointerObjects_[GetUnificationRoot(index)].PointeesEscaping;
281 return PointerObjects_[GetUnificationRoot(index)].PointsToExternal;
297 auto root = GetUnificationRoot(index);
298 return PointerObjects_[root].CanTrackPointeesImplicitly();
314 return PointerObjects_[GetUnificationRoot(index)].StoredAsScalar;
330 return PointerObjects_[GetUnificationRoot(index)].LoadedAsScalar;
341 while (PointerObjectParents_[index] != index)
343 auto & parent = PointerObjectParents_[index];
344 auto grandparent = PointerObjectParents_[parent];
345 index = parent = grandparent;
355 return GetUnificationRoot(index) == index;
367 if (newRoot == oldRoot)
374 std::swap(newRoot, oldRoot);
424 template<
typename NewPo
inteeFunctor>
429 NewPointeeFunctor & onNewPointee)
434 if (supersetRoot == subsetRoot)
442 bool modified =
false;
445 if (P_super.insert(pointee))
447 onNewPointee(pointee);
477 newPointees.
insert(pointee);
508 std::unique_ptr<PointerObjectSet>
511 return std::make_unique<PointerObjectSet>(*
this);
569 bool modified =
false;
585 bool modified =
false;
604 template<
typename MarkAsPo
inteesEscaping,
typename MarkAsPo
intsToExternal>
609 MarkAsPointeesEscaping & markAsPointeesEscaping,
610 MarkAsPointsToExternal & markAsPointsToExternal)
621 markAsPointeesEscaping(inputRegisterPO.value());
624 for (
size_t n = 0; n < callNode.
noutputs(); n++)
626 const auto & outputRegister = *callNode.
output(n);
628 if (outputRegisterPO)
629 markAsPointsToExternal(outputRegisterPO.value());
642 template<
typename MarkAsPo
inteesEscaping,
typename MarkAsPo
intsToExternal>
648 MarkAsPointeesEscaping & markAsPointeesEscaping,
649 MarkAsPointsToExternal & markAsPointsToExternal)
658 markAsPointeesEscaping,
659 markAsPointsToExternal);
666 template<
typename MakeSupersetFunctor>
672 MakeSupersetFunctor & makeSuperset)
680 const auto & argumentRegister = *lambdaArgs[n];
684 if (!inputRegisterPO || !argumentRegisterPO)
687 makeSuperset(*argumentRegisterPO, *inputRegisterPO);
695 template<
typename MakeSupersetFunctor>
701 MakeSupersetFunctor & makeSuperset)
706 for (
size_t n = 0; n < callNode.
noutputs() && n < lambdaResults.size(); n++)
708 const auto & outputRegister = *callNode.
output(n);
709 const auto & resultRegister = *lambdaResults[n]->origin();
713 if (!outputRegisterPO || !resultRegisterPO)
716 makeSuperset(*outputRegisterPO, *resultRegisterPO);
731 template<
typename MakeSupersetFunctor>
737 MakeSupersetFunctor & makeSuperset)
756 bool modified =
false;
782 MarkAsPointeesEscaping,
783 MarkAsPointsToExternal);
798 bool modified =
false;
822 std::queue<PointerObjectIndex> pointeeEscapers;
827 pointeeEscapers.push(idx);
831 while (!pointeeEscapers.empty())
834 pointeeEscapers.pop();
845 if (!prevHasPointeesEscaping)
848 pointeeEscapers.push(unificationRoot);
867 template<
typename MarkAsPo
inteesEscapingFunctor,
typename MarkAsPo
intsToExternalFunctor>
872 MarkAsPointeesEscapingFunctor & markAsPointeesEscaping,
873 MarkAsPointsToExternalFunctor & markAsPointsToExternal)
882 for (
auto argument : lambdaNode.GetFunctionArguments())
893 markAsPointsToExternal(argumentPO.value());
897 for (
auto result : lambdaNode.GetFunctionResults())
908 markAsPointeesEscaping(resultPO.value());
915 bool modified =
false;
975 const std::vector<PointerObjectConstraintSet::ConstraintVariant> &
984 size_t numBaseConstraints = 0;
990 return numBaseConstraints;
993 std::pair<size_t, size_t>
996 size_t numScalarFlagConstraints = 0;
997 size_t numOtherFlagConstraints = 0;
1001 numOtherFlagConstraints++;
1007 numOtherFlagConstraints++;
1009 numOtherFlagConstraints++;
1011 numScalarFlagConstraints++;
1013 numScalarFlagConstraints++;
1015 return { numScalarFlagConstraints, numOtherFlagConstraints };
1027 std::ostringstream label;
1059 label << (sep ?
", +" :
"+");
1071 label <<
"\nCantPoint";
1099 node.SetFillColor(
"#FFFF99");
1115 for (
auto [importArgument, index] : set.
GetImportMap())
1119 std::unordered_map<PointerObjectIndex, size_t> associationSuffix;
1122 auto suffix = associationSuffix[index]++;
1137 const std::vector<PointerObjectConstraintSet::ConstraintVariant> & constraints,
1141 size_t nextCallConstraintIndex = 0;
1142 for (
auto & constraint : constraints)
1144 if (
auto * supersetConstraint = std::get_if<SupersetConstraint>(&constraint))
1147 graph.
GetNode(supersetConstraint->GetSubset()),
1148 graph.
GetNode(supersetConstraint->GetSuperset()));
1150 else if (
auto * storeConstraint = std::get_if<StoreConstraint>(&constraint))
1153 graph.
GetNode(storeConstraint->GetValue()),
1154 graph.
GetNode(storeConstraint->GetPointer()));
1156 edge.SetArrowHead(
"normalodot");
1158 else if (
auto * loadConstraint = std::get_if<LoadConstraint>(&constraint))
1161 graph.
GetNode(loadConstraint->GetPointer()),
1162 graph.
GetNode(loadConstraint->GetValue()));
1164 edge.SetArrowTail(
"odot");
1166 else if (
auto * callConstraint = std::get_if<FunctionCallConstraint>(&constraint))
1168 auto callConstraintIndex = nextCallConstraintIndex++;
1169 auto & pointerNode = graph.
GetNode(callConstraint->GetPointer());
1173 auto & callNode = callConstraint->GetCallNode();
1176 if (
auto inputRegister =
1179 const auto label =
util::strfmt(
"call", callConstraintIndex,
" input", i);
1183 for (
size_t i = 0; i < callNode.noutputs(); i++)
1187 const auto label =
util::strfmt(
"call", callConstraintIndex,
" output", i);
1209 size_t nextFunctionIndex = 0;
1213 const auto functionIndex = nextFunctionIndex++;
1217 auto args =
function->GetFunctionArguments();
1218 for (
size_t i = 0; i < args.size(); i++)
1222 const auto label =
util::strfmt(
"function", functionIndex,
" arg", i);
1226 auto results =
function->GetFunctionResults();
1227 for (
size_t i = 0; i < results.size(); i++)
1231 const auto label =
util::strfmt(
"function", functionIndex,
" res", i);
1242 graph.
SetLabel(
"Andersen subset graph");
1252 std::tuple<size_t, std::vector<util::HashSet<PointerObjectIndex>>, std::vector<bool>>
1259 std::vector<util::HashSet<PointerObjectIndex>> successors(totalNodeCount);
1260 std::vector<bool> isDirectNode(totalNodeCount,
false);
1269 for (
auto arg : lambda->GetFunctionArguments())
1272 isDirectNode[*argumentPO] =
false;
1279 if (
auto * supersetConstraint = std::get_if<SupersetConstraint>(&constraint))
1284 successors[subset].insert(superset);
1287 successors[subset + derefNodeOffset].insert(superset + derefNodeOffset);
1289 else if (
auto * storeConstraint = std::get_if<StoreConstraint>(&constraint))
1295 successors[value].insert(pointer + derefNodeOffset);
1297 else if (
auto * loadConstraint = std::get_if<LoadConstraint>(&constraint))
1303 successors[pointer + derefNodeOffset].insert(value);
1305 else if (
auto * callConstraint = std::get_if<FunctionCallConstraint>(&constraint))
1307 auto & callNode = callConstraint->GetCallNode();
1309 for (
size_t n = 0; n < callNode.noutputs(); n++)
1312 isDirectNode[*resultPO] =
false;
1319 return { totalNodeCount, std::move(successors), std::move(isDirectNode) };
1329 static std::vector<int64_t>
1333 std::vector<size_t> & sccIndex,
1334 std::vector<size_t> & reverseTopologicalOrder,
1335 std::vector<bool> & sccHasDirectNodesOnly)
1338 int64_t nextEquivalenceSetLabel = 0;
1339 const int64_t NO_EQUIVALENCE_SET_LABEL = -1;
1340 std::vector<int64_t> equivalenceSetLabels(numSccs, NO_EQUIVALENCE_SET_LABEL);
1343 const int64_t NO_PREDECESSOR_YET = -1;
1344 const int64_t SEVERAL_PREDECESSORS = -2;
1345 std::vector<int64_t> predecessorEquivalenceLabels(numSccs, NO_PREDECESSOR_YET);
1349 for (
auto it = reverseTopologicalOrder.rbegin(); it != reverseTopologicalOrder.rend(); ++it)
1351 const auto node = *it;
1352 const auto scc = sccIndex[node];
1355 if (equivalenceSetLabels[scc] == NO_EQUIVALENCE_SET_LABEL)
1359 if (sccHasDirectNodesOnly[scc] && predecessorEquivalenceLabels[scc] != NO_PREDECESSOR_YET
1360 && predecessorEquivalenceLabels[scc] != SEVERAL_PREDECESSORS)
1362 equivalenceSetLabels[scc] = predecessorEquivalenceLabels[scc];
1366 equivalenceSetLabels[scc] = nextEquivalenceSetLabel++;
1371 for (
auto successor : successors[node].Items())
1373 const auto successorSCC = sccIndex[successor];
1374 if (predecessorEquivalenceLabels[successorSCC] == SEVERAL_PREDECESSORS)
1377 if (predecessorEquivalenceLabels[successorSCC] == NO_PREDECESSOR_YET)
1379 predecessorEquivalenceLabels[successorSCC] = equivalenceSetLabels[scc];
1381 else if (predecessorEquivalenceLabels[successorSCC] != equivalenceSetLabels[scc])
1383 predecessorEquivalenceLabels[successorSCC] = SEVERAL_PREDECESSORS;
1388 return equivalenceSetLabels;
1400 auto totalNodeCount = std::get<0>(subsetGraph);
1401 auto & successors = std::get<1>(subsetGraph);
1402 auto & isDirectNode = std::get<2>(subsetGraph);
1406 return successors[node].Items();
1410 std::vector<size_t> sccIndex;
1411 std::vector<size_t> reverseTopologicalOrder;
1412 auto numSccs = util::FindStronglyConnectedComponents<size_t>(
1416 reverseTopologicalOrder);
1419 std::vector<bool> sccHasDirectNodesOnly(numSccs,
true);
1420 for (
size_t node = 0; node < totalNodeCount; node++)
1422 if (!isDirectNode[node])
1423 sccHasDirectNodesOnly[sccIndex[node]] =
false;
1431 reverseTopologicalOrder,
1432 sccHasDirectNodesOnly);
1435 size_t numUnifications = 0;
1436 std::vector<std::optional<PointerObjectIndex>> unificationRoot(
1437 equivalenceSetLabels.size(),
1445 const auto equivalenceSetLabel = equivalenceSetLabels[sccIndex[i]];
1448 if (unificationRoot[equivalenceSetLabel])
1450 unificationRoot[equivalenceSetLabel] =
1455 unificationRoot[equivalenceSetLabel] = i;
1459 if (storeRefCycleUnificationRoot)
1466 std::vector<std::optional<PointerObjectIndex>> unificationRootPerSCC(numSccs, std::nullopt);
1469 if (!unificationRootPerSCC[sccIndex[i]])
1477 if (
auto optRoot = unificationRootPerSCC[sccIndex[i + derefNodeOffset]])
1484 return numUnifications;
1491 std::vector<ConstraintVariant> newConstraints;
1502 if (
auto * supersetConstraint = std::get_if<SupersetConstraint>(&constraint))
1508 if (supersetRoot == subsetRoot)
1511 if (addedSupersetConstraints.
insert({ supersetRoot, subsetRoot }))
1514 else if (
auto * storeConstraint = std::get_if<StoreConstraint>(&constraint))
1519 if (addedStoreConstraints.
insert({ pointerRoot, valueRoot }))
1522 else if (
auto * loadConstraint = std::get_if<LoadConstraint>(&constraint))
1527 if (addedLoadConstraints.
insert({ pointerRoot, valueRoot }))
1528 newConstraints.emplace_back(
LoadConstraint(valueRoot, pointerRoot));
1530 else if (
auto * functionCallConstraint = std::get_if<FunctionCallConstraint>(&constraint))
1533 auto & callNode = functionCallConstraint->GetCallNode();
1535 if (addedCallConstraints.
insert({ pointerRoot, &callNode }))
1542 size_t reduction =
Constraints_.size() - newConstraints.size();
1549 bool EnableOnlineCycleDetection,
1550 bool EnableHybridCycleDetection,
1551 bool EnableLazyCycleDetection,
1552 bool EnableDifferencePropagation,
1553 bool EnablePreferImplicitPointees>
1561 if constexpr (EnableOnlineCycleDetection)
1563 static_assert(!EnableHybridCycleDetection,
"OnlineCD can not be combined with HybridCD");
1564 static_assert(!EnableLazyCycleDetection,
"OnlineCD can not be combined with LazyCD");
1582 if (
const auto * ssConstraint = std::get_if<SupersetConstraint>(&constraint))
1589 if (superset != subset)
1590 supersetEdges[subset].insert(superset);
1592 else if (
const auto * storeConstraint = std::get_if<StoreConstraint>(&constraint))
1597 storeConstraints[pointer].insert(value);
1599 else if (
const auto * loadConstraint = std::get_if<LoadConstraint>(&constraint))
1604 loadConstraints[pointer].insert(value);
1606 else if (
const auto * callConstraint = std::get_if<FunctionCallConstraint>(&constraint))
1609 const auto & callNode = callConstraint->GetCallNode();
1611 callConstraints[pointer].insert(&callNode);
1616 if constexpr (EnableDifferencePropagation)
1624 if constexpr (EnableDifferencePropagation)
1636 if constexpr (EnableDifferencePropagation)
1659 const auto nonRoot = root == aRoot ? bRoot : aRoot;
1662 supersetEdges[root].UnionWithAndClear(supersetEdges[nonRoot]);
1665 supersetEdges[root].Remove(root);
1666 supersetEdges[root].Remove(nonRoot);
1668 storeConstraints[root].UnionWithAndClear(storeConstraints[nonRoot]);
1670 loadConstraints[root].UnionWithAndClear(loadConstraints[nonRoot]);
1672 callConstraints[root].UnionWithAndClear(callConstraints[nonRoot]);
1674 if constexpr (EnableDifferencePropagation)
1677 if constexpr (EnableHybridCycleDetection)
1698 if constexpr (EnableDifferencePropagation)
1707 return supersetEdges[node].Items();
1713 if constexpr (EnableOnlineCycleDetection)
1718 if constexpr (EnableLazyCycleDetection)
1721 if constexpr (EnableHybridCycleDetection)
1724 if constexpr (EnablePreferImplicitPointees)
1732 worklist.PushWorkItem(i);
1740 worklist.PushWorkItem(index);
1748 worklist.PushWorkItem(index);
1759 if (superset == subset)
1762 if constexpr (EnablePreferImplicitPointees)
1773 MarkAsPointeesEscaping(subset);
1779 if (!supersetEdges[subset].insert(superset))
1783 if constexpr (EnableOnlineCycleDetection)
1787 if (optUnificationRoot)
1789 worklist.PushWorkItem(*optUnificationRoot);
1795 bool anyPropagation = MakePointsToSetSuperset(superset, subset);
1797 worklist.PushWorkItem(superset);
1803 if (optUnificationRoot)
1804 worklist.PushWorkItem(*optUnificationRoot);
1814 if (superset == subset || supersetEdges[subset].Contains(superset))
1816 newSupersetEdges.
insert({ superset, subset });
1819 const auto FlushNewSupersetEdges = [&]()
1821 for (
auto [superset, subset] : newSupersetEdges.
Items())
1822 AddSupersetEdge(superset, subset);
1823 newSupersetEdges.
Clear();
1848 const auto & newPointees = EnableDifferencePropagation
1855 const auto newPointsToExternal = EnableDifferencePropagation
1860 if constexpr (EnableHybridCycleDetection)
1866 auto & refUnificationRoot = refUnificationRootIt->second;
1871 bool anyUnification =
false;
1874 auto unificationMembers = newPointees;
1875 for (
const auto pointee : unificationMembers.Items())
1878 if (pointeeRoot == refUnificationRoot)
1882 anyUnification =
true;
1883 refUnificationRoot = UnifyPointerObjects(refUnificationRoot, pointeeRoot);
1889 worklist.PushWorkItem(refUnificationRoot);
1900 for (
auto superset : supersetEdges[node].Items())
1915 const auto newPointeesEscaping = EnableDifferencePropagation
1920 if (pointeesEscaping)
1924 const auto & newEscapingPointees =
1926 for (
const auto pointee : newEscapingPointees.Items())
1933 const bool rootAlreadyHasFlags =
1946 if (!rootAlreadyHasFlags)
1950 worklist.PushWorkItem(pointeeRoot);
1960 RemoveAllPointees(node);
1964 auto supersets = supersetEdges[node].Items();
1965 for (
auto it = supersets.begin(); it != supersets.end();)
1970 if (supersetParent == node)
1972 it = supersetEdges[node].Erase(it);
1977 if (EnablePreferImplicitPointees && pointeesEscaping
1980 it = supersetEdges[node].Erase(it);
1987 bool modified =
false;
1988 for (
const auto pointee : newPointees.Items())
1989 modified |= AddToPointsToSet(supersetParent, pointee);
1991 if (newPointsToExternal)
1995 worklist.PushWorkItem(supersetParent);
1997 if (EnableLazyCycleDetection && !newPointees.IsEmpty() && !modified)
2002 if (optUnificationRoot)
2005 worklist.PushWorkItem(*optUnificationRoot);
2012 for (
const auto value : storeConstraints[node].Items())
2015 for (
const auto pointee : newPointees.Items())
2016 QueueNewSupersetEdge(pointee, value);
2019 if (newPointsToExternal)
2020 MarkAsPointeesEscaping(value);
2026 for (
const auto pointee : newPointees.Items())
2028 MarkAsPointsToExternal(pointee);
2033 for (
const auto value : loadConstraints[node].Items())
2036 for (
const auto pointee : newPointees.Items())
2037 QueueNewSupersetEdge(value, pointee);
2040 if (newPointsToExternal)
2041 MarkAsPointsToExternal(value);
2047 for (
const auto pointee : newPointees.Items())
2049 MarkAsPointeesEscaping(pointee);
2054 for (
const auto callNode : callConstraints[node].Items())
2057 for (
const auto pointee : newPointees.Items())
2065 MarkAsPointeesEscaping,
2066 MarkAsPointsToExternal);
2072 if (newPointsToExternal)
2076 MarkAsPointeesEscaping,
2077 MarkAsPointsToExternal);
2082 if constexpr (EnableDifferencePropagation)
2085 if (newPointsToExternal)
2087 if (newPointeesEscaping)
2094 FlushNewSupersetEdges();
2101 constexpr
bool useTopologicalTraversal =
2102 std::is_same_v<Worklist, util::Workset<PointerObjectIndex>>;
2104 if constexpr (useTopologicalTraversal)
2106 std::vector<PointerObjectIndex> sccIndex;
2107 std::vector<PointerObjectIndex> reverseTopologicalOrder;
2111 while (worklist.HasMoreWorkItems())
2122 util::FindStronglyConnectedComponents<PointerObjectIndex>(
2125 GetSupersetEdgeSuccessors,
2127 reverseTopologicalOrder);
2131 for (
auto it = reverseTopologicalOrder.rbegin(); it != reverseTopologicalOrder.rend(); ++it)
2133 const auto node = *it;
2136 const auto nextIt = it + 1;
2137 if (nextIt != reverseTopologicalOrder.rend())
2139 auto & nextNode = *nextIt;
2140 if (sccIndex[node] == sccIndex[nextNode])
2143 auto unifiedNode = UnifyPointerObjects(node, nextNode);
2144 auto oldNode = unifiedNode == node ? nextNode : node;
2146 worklist.RemoveWorkItem(oldNode);
2148 worklist.PushWorkItem(unifiedNode);
2151 nextNode = unifiedNode;
2157 while (worklist.HasWorkItem(node))
2159 worklist.RemoveWorkItem(node);
2160 HandleWorkItem(node);
2168 while (worklist.HasMoreWorkItems())
2169 HandleWorkItem(worklist.PopWorkItem());
2172 if constexpr (EnableOnlineCycleDetection)
2178 if constexpr (EnableLazyCycleDetection)
2189 bool enableOnlineCycleDetection,
2190 bool enableHybridCycleDetection,
2191 bool enableLazyCycleDetection,
2192 bool enableDifferencePropagation,
2193 bool enablePreferImplicitPointees)
2199 const auto Dispatch = [&](
auto tWorklist,
2200 auto tOnlineCycleDetection,
2201 auto tHybridCycleDetection,
2202 auto tLazyCycleDetection,
2203 auto tDifferencePropagation,
2206 using Worklist = std::remove_pointer_t<decltype(tWorklist)>;
2207 constexpr
bool vOnlineCycleDetection = decltype(tOnlineCycleDetection)::value;
2208 constexpr
bool vHybridCycleDetection = decltype(tHybridCycleDetection)::value;
2209 constexpr
bool vLazyCycleDetection = decltype(tLazyCycleDetection)::value;
2210 constexpr
bool vDifferencePropagation = decltype(tDifferencePropagation)::value;
2211 constexpr
bool vPreferImplicitPointees = decltype(tPreferImplicitPointees)::value;
2215 && (vOnlineCycleDetection || vHybridCycleDetection || vLazyCycleDetection))
2217 JLM_UNREACHABLE(
"Can not enable online, hybrid or lazy cycle detection with the topo policy");
2219 if constexpr (vOnlineCycleDetection && (vHybridCycleDetection || vLazyCycleDetection))
2221 JLM_UNREACHABLE(
"Can not enable hybrid or lazy cycle detection with online cycle detection");
2228 vOnlineCycleDetection,
2229 vHybridCycleDetection,
2230 vLazyCycleDetection,
2231 vDifferencePropagation,
2232 vPreferImplicitPointees>(statistics);
2258 std::variant<std::true_type, std::false_type> onlineCycleDetectionVariant;
2259 if (enableOnlineCycleDetection)
2260 onlineCycleDetectionVariant = std::true_type{};
2262 onlineCycleDetectionVariant = std::false_type{};
2264 std::variant<std::true_type, std::false_type> hybridCycleDetectionVariant;
2265 if (enableHybridCycleDetection)
2266 hybridCycleDetectionVariant = std::true_type{};
2268 hybridCycleDetectionVariant = std::false_type{};
2270 std::variant<std::true_type, std::false_type> lazyCycleDetectionVariant;
2271 if (enableLazyCycleDetection)
2272 lazyCycleDetectionVariant = std::true_type{};
2274 lazyCycleDetectionVariant = std::false_type{};
2276 std::variant<std::true_type, std::false_type> differencePropagationVariant;
2277 if (enableDifferencePropagation)
2278 differencePropagationVariant = std::true_type{};
2280 differencePropagationVariant = std::false_type{};
2282 std::variant<std::true_type, std::false_type> preferImplicitPropagationVariant;
2283 if (enablePreferImplicitPointees)
2284 preferImplicitPropagationVariant = std::true_type{};
2286 preferImplicitPropagationVariant = std::false_type{};
2291 onlineCycleDetectionVariant,
2292 hybridCycleDetectionVariant,
2293 lazyCycleDetectionVariant,
2294 differencePropagationVariant,
2295 preferImplicitPropagationVariant);
2304 return "LeastRecentlyFired";
2306 return "TwoPhaseLeastRecentlyFired";
2308 return "TopologicalSort";
2310 return "FirstInFirstOut";
2312 return "LastInFirstOut";
2321 size_t numIterations = 0;
2324 bool modified =
true;
2334 [&](
auto & constraint)
2336 modified |= constraint.ApplyDirectly(
Set_);
2345 return numIterations;
2348 std::pair<std::unique_ptr<PointerObjectSet>, std::unique_ptr<PointerObjectConstraintSet>>
2352 auto constraintClone = std::make_unique<PointerObjectConstraintSet>(*setClone);
2354 constraintClone->AddConstraint(constraint);
2356 return std::make_pair(std::move(setClone), std::move(constraintClone));
static rvsdg::Input * Argument(const rvsdg::Node &node, const size_t n)
static size_t NumArguments(const rvsdg::Node &node) 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 OnRemoveAllPointees(PointerObjectIndex index)
void ClearNewPointees(PointerObjectIndex index)
static bool PropagateEscapedFlagsDirectly(PointerObjectSet &set)
static bool PropagateEscapedFunctionsDirectly(PointerObjectSet &set)
PointerObjectIndex Pointer_
const rvsdg::SimpleNode & CallNode_
bool ApplyDirectly(PointerObjectSet &set)
size_t NumCycleUnifications() const noexcept
size_t NumCyclesDetected() const noexcept
size_t NumCycleDetectionAttempts() const noexcept
std::optional< PointerObjectIndex > OnPropagatedNothing(PointerObjectIndex subset, PointerObjectIndex superset)
PointerObjectIndex Value_
bool ApplyDirectly(PointerObjectSet &set)
PointerObjectIndex Pointer_
size_t NumOnlineCyclesDetected() const noexcept
std::optional< PointerObjectIndex > MaintainTopologicalOrder(PointerObjectIndex subset, PointerObjectIndex superset)
void InitializeTopologicalOrdering()
size_t NumOnlineCycleUnifications() const noexcept
bool IsFrozen() const noexcept
@ TwoPhaseLeastRecentlyFired
size_t NormalizeConstraints()
void RunWorklistSolver(WorklistStatistics &statistics)
size_t NumBaseConstraints() const noexcept
std::unordered_map< PointerObjectIndex, PointerObjectIndex > RefNodeUnificationRoot_
std::pair< size_t, size_t > NumFlagConstraints() const noexcept
void AddPointerPointeeConstraint(PointerObjectIndex pointer, PointerObjectIndex pointee)
std::vector< ConstraintVariant > Constraints_
size_t PerformOfflineVariableSubstitution(bool storeRefCycleUnificationRoot)
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)
std::tuple< size_t, std::vector< util::HashSet< PointerObjectIndex > >, std::vector< bool > > CreateOvsSubsetGraph()
bool ConstraintSetFrozen_
WorklistStatistics SolveUsingWorklist(WorklistSolverPolicy policy, bool enableOnlineCycleDetection, bool enableHybridCycleDetection, bool enableLazyCycleDetection, bool enableDifferencePropagation, bool enablePreferImplicitPropation)
const std::vector< ConstraintVariant > & GetConstraints() const noexcept
std::variant< SupersetConstraint, StoreConstraint, LoadConstraint, FunctionCallConstraint > ConstraintVariant
void AddPointsToExternalConstraint(PointerObjectIndex pointer)
void AddRegisterContentEscapedConstraint(PointerObjectIndex registerIndex)
static const char * WorklistSolverPolicyToString(WorklistSolverPolicy policy)
const util::BijectiveMap< const rvsdg::LambdaNode *, PointerObjectIndex > & GetFunctionMap() const noexcept
PointerObjectIndex CreateMallocMemoryObject(const rvsdg::SimpleNode &mallocNode, bool canPoint)
PointerObjectIndex UnifyPointerObjects(PointerObjectIndex object1, PointerObjectIndex object2)
PointerObjectIndex AddPointerObject(PointerObjectKind kind, bool canPoint)
size_t NumMemoryPointerObjects() const noexcept
bool IsPointingTo(PointerObjectIndex pointer, PointerObjectIndex pointee) const
PointerObjectIndex CreateDummyRegisterPointerObject()
PointerObjectKind GetPointerObjectKind(PointerObjectIndex index) const noexcept
size_t GetNumSetInsertionAttempts() const noexcept
std::vector< PointerObjectIndex > PointerObjectParents_
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetMallocMap() const noexcept
bool IsPointerObjectRegister(PointerObjectIndex index) const noexcept
size_t GetNumExplicitPointeesRemoved() const noexcept
std::unordered_map< const rvsdg::Output *, PointerObjectIndex > RegisterMap_
PointerObjectIndex CreateGlobalMemoryObject(const rvsdg::DeltaNode &deltaNode, bool canPoint)
void MapRegisterToExistingPointerObject(const rvsdg::Output &rvsdgOutput, PointerObjectIndex pointerObject)
size_t NumRegisterPointerObjects() const noexcept
const util::HashSet< PointerObjectIndex > & GetPointsToSet(PointerObjectIndex index) const
bool HasPointeesEscaping(PointerObjectIndex index) const noexcept
bool PropagateNewPointees(PointerObjectIndex superset, PointerObjectIndex subset, NewPointeeFunctor &onNewPointee)
bool IsLoadedAsScalar(PointerObjectIndex index) const noexcept
void RemoveAllPointees(PointerObjectIndex index)
size_t NumSetInsertionAttempts_
size_t NumExplicitPointeesRemoved_
size_t NumMemoryPointerObjectsCanPoint() const noexcept
std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > AllocaMap_
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
std::vector< uint8_t > PointerObjectRank_
bool MarkAsLoadingAsScalar(PointerObjectIndex index)
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetAllocaMap() const noexcept
std::unordered_map< const rvsdg::DeltaNode *, PointerObjectIndex > GlobalMap_
std::unique_ptr< PointerObjectSet > Clone() const
bool IsPointingToExternal(PointerObjectIndex index) const noexcept
std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > MallocMap_
bool HasIdenticalSolAs(const PointerObjectSet &other) const
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
std::vector< util::HashSet< PointerObjectIndex > > PointsToSets_
PointerObjectIndex CreateAllocaMemoryObject(const rvsdg::SimpleNode &allocaNode, bool canPoint)
bool CanTrackPointeesImplicitly(PointerObjectIndex index) const noexcept
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)
std::vector< PointerObject > PointerObjects_
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)
util::BijectiveMap< const rvsdg::LambdaNode *, PointerObjectIndex > FunctionMap_
PointerObjectIndex GetFunctionMemoryObject(const rvsdg::LambdaNode &lambdaNode) const
bool MakePointsToSetSuperset(PointerObjectIndex superset, PointerObjectIndex subset)
std::optional< PointerObjectIndex > TryGetRegisterPointerObject(const rvsdg::Output &rvsdgOutput) const
std::unordered_map< const LlvmGraphImport *, PointerObjectIndex > ImportMap_
size_t NumPointerObjectsOfKind(PointerObjectKind kind) const noexcept
PointerObjectIndex Pointer_
PointerObjectIndex Value_
bool ApplyDirectly(PointerObjectSet &set)
PointerObjectIndex Superset_
PointerObjectIndex Subset_
bool ApplyDirectly(PointerObjectSet &set)
std::vector< rvsdg::Output * > GetFunctionArguments() const
std::vector< rvsdg::Input * > GetFunctionResults() const
size_t noutputs() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeOutput * output(size_t index) const noexcept
bool insert(ItemType item)
std::size_t Size() const noexcept
IteratorRange< ItemConstIterator > Items() const noexcept
bool IsEmpty() const noexcept
void SetStyle(std::string style)
void SetLabel(std::string label)
void SetAttributeObject(const std::string &attribute, uintptr_t object)
void AppendToLabel(std::string_view text, std::string_view sep="\n")
Node & GetNode(size_t index)
size_t NumNodes() const noexcept
Edge & CreateDirectedEdge(Port &from, Port &to)
#define JLM_UNREACHABLE(msg)
static void HandleLambdaCallParameters(PointerObjectSet &set, const rvsdg::SimpleNode &callNode, const rvsdg::LambdaNode &lambdaNode, MakeSupersetFunctor &makeSuperset)
static std::string CreateSubsetGraphNodeLabel(PointerObjectSet &set, PointerObjectIndex index)
static void CreateSubsetGraphNodes(PointerObjectSet &set, util::graph::Graph &graph)
static void HandleLambdaCallReturnValues(PointerObjectSet &set, const rvsdg::SimpleNode &callNode, const rvsdg::LambdaNode &lambdaNode, MakeSupersetFunctor &makeSuperset)
static void HandleEscapedFunction(PointerObjectSet &set, PointerObjectIndex lambda, MarkAsPointeesEscapingFunctor &markAsPointeesEscaping, MarkAsPointsToExternalFunctor &markAsPointsToExternal)
static void LabelFunctionsArgumentsAndReturnValues(PointerObjectSet &set, util::graph::Graph &graph)
void HandleCallingExternalFunction(PointerObjectSet &set, const rvsdg::SimpleNode &callNode, MarkAsPointeesEscaping &markAsPointeesEscaping, MarkAsPointsToExternal &markAsPointsToExternal)
uint32_t PointerObjectIndex
static constexpr bool ENABLE_UNIFICATION
static void HandleCallingImportedFunction(PointerObjectSet &set, const rvsdg::SimpleNode &callNode, [[maybe_unused]] PointerObjectIndex imported, MarkAsPointeesEscaping &markAsPointeesEscaping, MarkAsPointsToExternal &markAsPointsToExternal)
static std::vector< int64_t > AssignOvsEquivalenceSetLabels(std::vector< util::HashSet< PointerObjectIndex >> &successors, size_t numSccs, std::vector< size_t > &sccIndex, std::vector< size_t > &reverseTopologicalOrder, std::vector< bool > &sccHasDirectNodesOnly)
static void CreateSubsetGraphEdges(const PointerObjectSet &set, const std::vector< PointerObjectConstraintSet::ConstraintVariant > &constraints, util::graph::Graph &graph)
static void HandleCallingLambdaFunction(PointerObjectSet &set, const rvsdg::SimpleNode &callNode, PointerObjectIndex lambda, MakeSupersetFunctor &makeSuperset)
static std::string strfmt(Args... args)
std::optional< size_t > NumLazyCyclesDetected
std::optional< size_t > NumLazyCycleUnifications
std::optional< size_t > NumOnlineCycleUnifications
size_t NumWorkItemsPopped
std::optional< size_t > NumTopologicalWorklistSweeps
std::optional< size_t > NumOnlineCyclesDetected
std::optional< size_t > NumLazyCyclesDetectionAttempts
std::optional< size_t > NumPipExplicitPointeesRemoved
std::optional< size_t > NumHybridCycleUnifications
size_t NumWorkItemNewPointees
static const char *const Dashed
static const char *const Rectangle
static const char *const Oval