32 return IsOrContains<PointerType>(type) || is<rvsdg::FunctionType>(type);
38 std::ostringstream str;
45 str <<
"Solver=Naive_";
49 str <<
"Solver=Worklist_";
70 auto result = str.str();
71 result.erase(result.size() - 1, 1);
75std::vector<Andersen::Configuration>
78 std::vector<Configuration> configs;
81 config.EnablePreferImplicitPointees(
false);
82 configs.push_back(config);
83 config.EnablePreferImplicitPointees(
true);
84 configs.push_back(config);
88 config.EnableDifferencePropagation(
false);
89 PickPreferImplicitPointees(config);
90 config.EnableDifferencePropagation(
true);
91 PickPreferImplicitPointees(config);
95 config.EnableLazyCycleDetection(
false);
96 PickDifferencePropagation(config);
97 config.EnableLazyCycleDetection(
true);
98 PickDifferencePropagation(config);
102 config.EnableHybridCycleDetection(
false);
103 PickLazyCycleDetection(config);
105 if (config.IsOfflineVariableSubstitutionEnabled())
107 config.EnableHybridCycleDetection(
true);
108 PickLazyCycleDetection(config);
113 config.EnableOnlineCycleDetection(
false);
114 PickHybridCycleDetection(config);
115 config.EnableOnlineCycleDetection(
true);
117 PickDifferencePropagation(config);
122 config.SetWorklistSolverPolicy(Policy::LeastRecentlyFired);
123 PickOnlineCycleDetection(config);
124 config.SetWorklistSolverPolicy(Policy::TwoPhaseLeastRecentlyFired);
125 PickOnlineCycleDetection(config);
126 config.SetWorklistSolverPolicy(Policy::LastInFirstOut);
127 PickOnlineCycleDetection(config);
128 config.SetWorklistSolverPolicy(Policy::FirstInFirstOut);
129 PickOnlineCycleDetection(config);
130 config.SetWorklistSolverPolicy(Policy::TopologicalSort);
131 PickDifferencePropagation(config);
135 config.EnableOfflineConstraintNormalization(
false);
136 configs.push_back(config);
137 config.EnableOfflineConstraintNormalization(
true);
138 configs.push_back(config);
142 config.SetSolver(Solver::Worklist);
143 PickWorklistPolicy(config);
144 config.SetSolver(Solver::Naive);
145 PickOfflineNormalization(config);
147 auto PickOfflineVariableSubstitution = [&](
Configuration config)
149 config.EnableOfflineVariableSubstitution(
false);
151 config.EnableOfflineVariableSubstitution(
true);
156 PickOfflineVariableSubstitution(NaiveSolverConfiguration());
166 static constexpr const char * NumPointerObjects_ =
"#PointerObjects";
167 static constexpr const char * NumMemoryPointerObjects_ =
"#MemoryPointerObjects";
168 static constexpr const char * NumMemoryPointerObjectsCanPoint_ =
"#MemoryPointerObjectsCanPoint";
169 static constexpr const char * NumRegisterPointerObjects_ =
"#RegisterPointerObjects";
171 static constexpr const char * NumRegistersMappedToPointerObject_ =
172 "#RegistersMappedToPointerObject";
173 static constexpr const char * NumAllocaPointerObjects =
"#AllocaPointerObjects";
174 static constexpr const char * NumMallocPointerObjects =
"#MallocPointerObjects";
175 static constexpr const char * NumGlobalPointerObjects =
"#GlobalPointerObjects";
176 static constexpr const char * NumFunctionPointerObjects =
"#FunctionPointerObjects";
177 static constexpr const char * NumImportPointerObjects =
"#ImportPointerObjects";
179 static constexpr const char * NumBaseConstraints_ =
"#BaseConstraints";
180 static constexpr const char * NumSupersetConstraints_ =
"#SupersetConstraints";
181 static constexpr const char * NumStoreConstraints_ =
"#StoreConstraints";
182 static constexpr const char * NumLoadConstraints_ =
"#LoadConstraints";
183 static constexpr const char * NumFunctionCallConstraints_ =
"#FunctionCallConstraints";
184 static constexpr const char * NumScalarFlagConstraints_ =
"#ScalarFlagConstraints";
185 static constexpr const char * NumOtherFlagConstraints_ =
"#OtherFlagConstraints";
187 static constexpr const char * Configuration_ =
"Configuration";
190 static constexpr const char * NumUnificationsOvs_ =
"#Unifications(OVS)";
191 static constexpr const char * NumConstraintsRemovedOfflineNorm_ =
192 "#ConstraintsRemoved(OfflineNorm)";
195 static constexpr const char * NumNaiveSolverIterations_ =
"#NaiveSolverIterations";
197 static constexpr const char * WorklistPolicy_ =
"WorklistPolicy";
198 static constexpr const char * NumWorklistSolverWorkItemsPopped_ =
199 "#WorklistSolverWorkItemsPopped";
200 static constexpr const char * NumWorklistSolverWorkItemsNewPointees_ =
201 "#WorklistSolverWorkItemsNewPointees";
202 static constexpr const char * NumTopologicalWorklistSweeps_ =
"#TopologicalWorklistSweeps";
205 static constexpr const char * NumOnlineCyclesDetected_ =
"#OnlineCyclesDetected";
206 static constexpr const char * NumOnlineCycleUnifications_ =
"#OnlineCycleUnifications";
208 static constexpr const char * NumHybridCycleUnifications_ =
"#HybridCycleUnifications";
210 static constexpr const char * NumLazyCycleDetectionAttempts_ =
"#LazyCycleDetectionAttempts";
211 static constexpr const char * NumLazyCyclesDetected_ =
"#LazyCyclesDetected";
212 static constexpr const char * NumLazyCycleUnifications_ =
"#LazyCycleUnifications";
214 static constexpr const char * NumPIPExplicitPointeesRemoved_ =
"#PIPExplicitPointeesRemoved";
219 static constexpr const char * NumSetInsertionAttempts_ =
"#PointsToSetInsertionAttempts";
222 static constexpr const char * NumExplicitPointeesRemoved_ =
"#ExplicitPointeesRemoved";
226 static constexpr const char * NumUnificationRoots_ =
"#UnificationRoots";
228 static constexpr const char * NumCanPointsEscaped_ =
"#CanPointsEscaped";
230 static constexpr const char * NumCantPointsEscaped_ =
"#CantPointsEscaped";
233 static constexpr const char * NumExplicitPointees_ =
"#ExplicitPointees";
236 static constexpr const char * NumExplicitPointsToRelations_ =
"#ExplicitPointsToRelations";
239 static constexpr const char * NumPointsToExternalFlags_ =
"#PointsToExternalFlags";
241 static constexpr const char * NumPointsToExternalRelations_ =
"#PointsToExternalRelations";
245 static constexpr const char * NumExplicitPointsToRelationsAmongPrecise_ =
246 "#ExplicitPointsToRelationsAmongPrecise";
249 static constexpr const char * NumPointeesEscapingFlags_ =
"#PointeesEscapingFlags";
251 static constexpr const char * NumPointeesEscapingRelations_ =
"#PointeesEscapingRelations";
255 static constexpr const char * NumPointsToRelations_ =
"#PointsToRelations";
258 static constexpr const char * NumDoubledUpPointees_ =
"#DoubledUpPointees";
260 static constexpr const char * NumDoubledUpPointsToRelations_ =
"#DoubledUpPointsToRelations";
263 static constexpr const char * NumCantPointUnifications_ =
"#CantPointUnifications";
265 static constexpr const char * NumCantPointExplicitPointees_ =
"#CantPointExplicitPointees";
267 static constexpr const char * AnalysisTimer_ =
"AnalysisTimer";
268 static constexpr const char * SetAndConstraintBuildingTimer_ =
"SetAndConstraintBuildingTimer";
269 static constexpr const char * OfflineVariableSubstitutionTimer_ =
"OVSTimer";
270 static constexpr const char * OfflineConstraintNormalizationTimer_ =
"OfflineNormTimer";
271 static constexpr const char * ConstraintSolvingNaiveTimer_ =
"ConstraintSolvingNaiveTimer";
272 static constexpr const char * ConstraintSolvingWorklistTimer_ =
"ConstraintSolvingWorklistTimer";
273 static constexpr const char * PointsToGraphConstructionTimer_ =
"PointsToGraphConstructionTimer";
274 static constexpr const char * PointsToGraphConstructionExternalToEscapedTimer_ =
275 "PointsToGraphConstructionExternalToEscapedTimer";
287 AddMeasurement(Label::NumRvsdgNodes, rvsdg::nnodes(&graph.GetRootRegion()));
288 AddTimer(AnalysisTimer_).start();
294 AddTimer(SetAndConstraintBuildingTimer_).start();
302 GetTimer(SetAndConstraintBuildingTimer_).stop();
305 AddMeasurement(NumPointerObjects_, set.NumPointerObjects());
306 AddMeasurement(NumMemoryPointerObjects_, set.NumMemoryPointerObjects());
307 AddMeasurement(NumMemoryPointerObjectsCanPoint_, set.NumMemoryPointerObjectsCanPoint());
308 AddMeasurement(NumRegisterPointerObjects_, set.NumRegisterPointerObjects());
309 AddMeasurement(NumRegistersMappedToPointerObject_, set.GetRegisterMap().size());
312 NumAllocaPointerObjects,
313 set.NumPointerObjectsOfKind(PointerObjectKind::AllocaMemoryObject));
315 NumMallocPointerObjects,
316 set.NumPointerObjectsOfKind(PointerObjectKind::MallocMemoryObject));
318 NumGlobalPointerObjects,
319 set.NumPointerObjectsOfKind(PointerObjectKind::GlobalMemoryObject));
321 NumFunctionPointerObjects,
322 set.NumPointerObjectsOfKind(PointerObjectKind::FunctionMemoryObject));
324 NumImportPointerObjects,
325 set.NumPointerObjectsOfKind(PointerObjectKind::ImportMemoryObject));
328 size_t numSupersetConstraints = 0;
329 size_t numStoreConstraints = 0;
330 size_t numLoadConstraints = 0;
331 size_t numFunctionCallConstraints = 0;
332 for (
const auto & constraint : constraints.GetConstraints())
334 numSupersetConstraints += std::holds_alternative<SupersetConstraint>(constraint);
335 numStoreConstraints += std::holds_alternative<StoreConstraint>(constraint);
336 numLoadConstraints += std::holds_alternative<LoadConstraint>(constraint);
337 numFunctionCallConstraints += std::holds_alternative<FunctionCallConstraint>(constraint);
339 AddMeasurement(NumBaseConstraints_, constraints.NumBaseConstraints());
340 AddMeasurement(NumSupersetConstraints_, numSupersetConstraints);
341 AddMeasurement(NumStoreConstraints_, numStoreConstraints);
342 AddMeasurement(NumLoadConstraints_, numLoadConstraints);
343 AddMeasurement(NumFunctionCallConstraints_, numFunctionCallConstraints);
344 const auto [scalarFlags, otherFlags] = constraints.NumFlagConstraints();
345 AddMeasurement(NumScalarFlagConstraints_, scalarFlags);
346 AddMeasurement(NumOtherFlagConstraints_, otherFlags);
352 AddTimer(OfflineVariableSubstitutionTimer_).start();
358 GetTimer(OfflineVariableSubstitutionTimer_).stop();
359 AddMeasurement(NumUnificationsOvs_, numUnifications);
365 AddTimer(OfflineConstraintNormalizationTimer_).start();
371 GetTimer(OfflineConstraintNormalizationTimer_).stop();
372 AddMeasurement(NumConstraintsRemovedOfflineNorm_, numConstraintsRemoved);
378 AddTimer(ConstraintSolvingNaiveTimer_).start();
384 GetTimer(ConstraintSolvingNaiveTimer_).stop();
385 AddMeasurement(NumNaiveSolverIterations_, numIterations);
391 AddTimer(ConstraintSolvingWorklistTimer_).start();
398 GetTimer(ConstraintSolvingWorklistTimer_).stop();
403 PointerObjectConstraintSet::WorklistSolverPolicyToString(statistics.Policy));
406 AddMeasurement(NumWorklistSolverWorkItemsPopped_, statistics.NumWorkItemsPopped);
407 AddMeasurement(NumWorklistSolverWorkItemsNewPointees_, statistics.NumWorkItemNewPointees);
409 if (statistics.NumTopologicalWorklistSweeps)
410 AddMeasurement(NumTopologicalWorklistSweeps_, *statistics.NumTopologicalWorklistSweeps);
412 if (statistics.NumOnlineCyclesDetected)
413 AddMeasurement(NumOnlineCyclesDetected_, *statistics.NumOnlineCyclesDetected);
415 if (statistics.NumOnlineCycleUnifications)
416 AddMeasurement(NumOnlineCycleUnifications_, *statistics.NumOnlineCycleUnifications);
418 if (statistics.NumHybridCycleUnifications)
419 AddMeasurement(NumHybridCycleUnifications_, *statistics.NumHybridCycleUnifications);
421 if (statistics.NumLazyCyclesDetectionAttempts)
422 AddMeasurement(NumLazyCycleDetectionAttempts_, *statistics.NumLazyCyclesDetectionAttempts);
424 if (statistics.NumLazyCyclesDetected)
425 AddMeasurement(NumLazyCyclesDetected_, *statistics.NumLazyCyclesDetected);
427 if (statistics.NumLazyCycleUnifications)
428 AddMeasurement(NumLazyCycleUnifications_, *statistics.NumLazyCycleUnifications);
430 if (statistics.NumPipExplicitPointeesRemoved)
431 AddMeasurement(NumPIPExplicitPointeesRemoved_, *statistics.NumPipExplicitPointeesRemoved);
437 AddMeasurement(Configuration_, config.
ToString());
446 size_t numUnificationRoots = 0;
448 size_t numCanPointEscaped = 0;
449 size_t numCantPointEscaped = 0;
451 size_t numExplicitPointees = 0;
452 size_t numExplicitPointsToRelations = 0;
453 size_t numExplicitPointeeRelationsAmongPrecise = 0;
455 size_t numPointsToExternalFlags = 0;
456 size_t numPointsToExternalRelations = 0;
457 size_t numPointeesEscapingFlags = 0;
458 size_t numPointeesEscapingRelations = 0;
460 size_t numDoubledUpPointees = 0;
461 size_t numDoubledUpPointsToRelations = 0;
470 numCanPointEscaped++;
472 numCantPointEscaped++;
479 numExplicitPointsToRelations += pointees.
Size();
484 numPointsToExternalRelations++;
485 for (
auto pointee : pointees.Items())
488 numDoubledUpPointsToRelations++;
495 numExplicitPointeeRelationsAmongPrecise += pointees.Size();
507 numUnificationRoots++;
509 numPointsToExternalFlags++;
511 numPointeesEscapingFlags++;
513 numExplicitPointees += pointees.Size();
517 for (
auto pointee : pointees.Items())
519 numDoubledUpPointees++;
523 size_t numCantPointUnifications = 0;
524 size_t numCantPointExplicitPointees = 0;
529 if (unificationHasCanPoint[i])
531 numCantPointUnifications++;
535 AddMeasurement(NumUnificationRoots_, numUnificationRoots);
536 AddMeasurement(NumCanPointsEscaped_, numCanPointEscaped);
537 AddMeasurement(NumCantPointsEscaped_, numCantPointEscaped);
539 AddMeasurement(NumExplicitPointees_, numExplicitPointees);
540 AddMeasurement(NumExplicitPointsToRelations_, numExplicitPointsToRelations);
542 NumExplicitPointsToRelationsAmongPrecise_,
543 numExplicitPointeeRelationsAmongPrecise);
545 AddMeasurement(NumPointsToExternalFlags_, numPointsToExternalFlags);
546 AddMeasurement(NumPointsToExternalRelations_, numPointsToExternalRelations);
547 AddMeasurement(NumPointeesEscapingFlags_, numPointeesEscapingFlags);
548 AddMeasurement(NumPointeesEscapingRelations_, numPointeesEscapingRelations);
552 size_t numPointsToRelations =
553 numExplicitPointsToRelations - numDoubledUpPointsToRelations
554 + numPointsToExternalRelations * (numCanPointEscaped + numCantPointEscaped);
556 AddMeasurement(NumPointsToRelations_, numPointsToRelations);
558 AddMeasurement(NumDoubledUpPointees_, numDoubledUpPointees);
559 AddMeasurement(NumDoubledUpPointsToRelations_, numDoubledUpPointsToRelations);
561 AddMeasurement(NumCantPointUnifications_, numCantPointUnifications);
562 AddMeasurement(NumCantPointExplicitPointees_, numCantPointExplicitPointees);
568 AddTimer(PointsToGraphConstructionTimer_).start();
574 AddTimer(PointsToGraphConstructionExternalToEscapedTimer_).start();
580 GetTimer(PointsToGraphConstructionExternalToEscapedTimer_).stop();
586 GetTimer(PointsToGraphConstructionTimer_).stop();
587 AddMeasurement(Label::NumPointsToGraphNodes, pointsToGraph.
numNodes());
588 AddMeasurement(Label::NumPointsToGraphAllocaNodes, pointsToGraph.
numAllocaNodes());
589 AddMeasurement(Label::NumPointsToGraphDeltaNodes, pointsToGraph.
numDeltaNodes());
590 AddMeasurement(Label::NumPointsToGraphImportNodes, pointsToGraph.
numImportNodes());
591 AddMeasurement(Label::NumPointsToGraphLambdaNodes, pointsToGraph.
numLambdaNodes());
592 AddMeasurement(Label::NumPointsToGraphMallocNodes, pointsToGraph.
numMallocNodes());
593 AddMeasurement(Label::NumPointsToGraphMemoryNodes, pointsToGraph.
numMemoryNodes());
594 AddMeasurement(Label::NumPointsToGraphRegisterNodes, pointsToGraph.
numRegisterNodes());
596 Label::NumPointsToGraphExternallyAvailableNodes,
600 Label::NumPointsToGraphNodesTargetsAllExternallyAvailable,
602 auto [numExplicitEdges, numEdges] = pointsToGraph.
numEdges();
603 AddMeasurement(Label::NumPointsToGraphExplicitEdges, numExplicitEdges);
604 AddMeasurement(Label::NumPointsToGraphEdges, numEdges);
610 GetTimer(AnalysisTimer_).stop();
613 static std::unique_ptr<Statistics>
616 return std::make_unique<Statistics>(sourceFile);
655 AnalyzePtrMask(node);
659 AnalyzeBitcast(node);
663 AnalyzeBits2ptr(node);
667 AnalyzePtrToInt(node);
671 AnalyzeConstantPointerNull(node);
695 AnalyzeMemmove(node);
699 AnalyzeConstantArray(node);
703 AnalyzeConstantStruct(node);
707 AnalyzeConstantAggregateZero(node);
711 AnalyzeInsertValue(node);
715 AnalyzeExtractValue(node);
723 AnalyzePointerToFunction(node);
727 AnalyzeFunctionToPointer(node);
731 AnalyzeIOBarrier(node);
744 for (size_t n = 0; n < node.ninputs(); n++)
745 JLM_ASSERT(!IsOrContainsPointerType(*node.input(n)->Type()));
752 const auto allocaOp = util::assertedCast<const AllocaOperation>(&node.
GetOperation());
754 const auto & outputRegister = *node.
output(0);
755 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
758 const auto allocaPO =
Set_->CreateAllocaMemoryObject(node, canPoint);
759 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, allocaPO);
768 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
771 const auto mallocPO =
Set_->CreateMallocMemoryObject(node,
true);
772 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, mallocPO);
783 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
787 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
792 Set_->MarkAsLoadingAsScalar(addressRegisterPO);
802 const auto addressRegisterPO =
Set_->GetRegisterPointerObject(addressRegister);
807 const auto valueRegisterPO =
Set_->GetRegisterPointerObject(valueRegister);
812 Set_->MarkAsStoringAsScalar(addressRegisterPO);
823 const auto callTargetPO =
Set_->GetRegisterPointerObject(callTarget);
826 for (
size_t n = 0; n < callNode.
noutputs(); n++)
828 const auto & outputRegister = *callNode.
output(n);
830 (void)
Set_->CreateRegisterPointerObject(outputRegister);
846 const auto & baseRegister = *node.
input(0)->
origin();
847 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
849 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
850 const auto & outputRegister = *node.
output(0);
851 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
860 const auto & baseRegister = *node.
input(0)->
origin();
861 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
863 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
864 const auto & outputRegister = *node.
output(0);
865 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
873 const auto & inputRegister = *node.
input(0)->
origin();
874 const auto & outputRegister = *node.
output(0);
883 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
884 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
891 const auto & output = *node.
output(0);
897 const auto outputPO =
Set_->CreateRegisterPointerObject(output);
905 const auto & inputRegister = *node.
input(0)->
origin();
906 JLM_ASSERT(is<PointerType>(inputRegister.Type()));
909 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
910 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
917 const auto & output = *node.
output(0);
922 (void)
Set_->CreateRegisterPointerObject(output);
929 const auto & output = *node.
output(0);
936 (void)
Set_->CreateRegisterPointerObject(output);
943 const auto & output = *node.
output(0);
950 (void)
Set_->CreateRegisterPointerObject(output);
957 const auto & output = *node.
output(0);
966 auto operandPO =
Set_->GetRegisterPointerObject(operand);
967 Set_->MapRegisterToExistingPointerObject(output, operandPO);
975 auto & dstAddressRegister = *node.
input(0)->
origin();
976 auto & srcAddressRegister = *node.
input(1)->
origin();
977 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
978 JLM_ASSERT(is<PointerType>(srcAddressRegister.Type()));
980 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
981 const auto srcAddressRegisterPO =
Set_->GetRegisterPointerObject(srcAddressRegister);
984 const auto dummyPO =
Set_->CreateDummyRegisterPointerObject();
997 auto & dstAddressRegister = *node.
input(0)->
origin();
998 auto & srcAddressRegister = *node.
input(1)->
origin();
999 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
1000 JLM_ASSERT(is<PointerType>(srcAddressRegister.Type()));
1002 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
1003 const auto srcAddressRegisterPO =
Set_->GetRegisterPointerObject(srcAddressRegister);
1006 const auto dummyPO =
Set_->CreateDummyRegisterPointerObject();
1020 JLM_ASSERT(is<PointerType>(dstAddressRegister.Type()));
1022 const auto dstAddressRegisterPO =
Set_->GetRegisterPointerObject(dstAddressRegister);
1024 Set_->MarkAsStoringAsScalar(dstAddressRegisterPO);
1036 auto & outputRegister = *node.
output(0);
1037 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1039 for (
size_t n = 0; n < node.
ninputs(); n++)
1041 const auto & inputRegister = *node.
input(n)->
origin();
1044 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1058 auto & outputRegister = *node.
output(0);
1059 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1061 for (
size_t n = 0; n < node.
ninputs(); n++)
1063 const auto & inputRegister = *node.
input(n)->
origin();
1067 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1076 auto & output = *node.
output(0);
1083 (void)
Set_->CreateRegisterPointerObject(output);
1098 const auto & result = *node.
output(0);
1102 const auto & inputRegister = *node.
input(0)->
origin();
1103 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1111 const auto elementPO =
Set_->GetRegisterPointerObject(element);
1112 const auto resultPO =
Set_->CreateRegisterPointerObject(result);
1119 Set_->MapRegisterToExistingPointerObject(result, inputRegisterPO);
1128 const auto & result = *node.
output(0);
1132 const auto & inputRegister = *node.
input(0)->
origin();
1133 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1135 Set_->MapRegisterToExistingPointerObject(result, inputRegisterPO);
1148 for (
size_t i = 0; i < node.
ninputs(); i++)
1153 const auto & inputRegister = *node.
input(i)->
origin();
1154 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1155 Constraints_->AddRegisterContentEscapedConstraint(inputRegisterPO);
1166 const auto & baseRegister = *node.
input(0)->
origin();
1167 JLM_ASSERT(is<PointerType>(baseRegister.Type()));
1169 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1170 const auto & outputRegister = *node.
output(0);
1171 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1181 const auto & baseRegister = *node.
input(0)->
origin();
1182 JLM_ASSERT(is<rvsdg::FunctionType>(baseRegister.Type()));
1184 const auto baseRegisterPO =
Set_->GetRegisterPointerObject(baseRegister);
1185 const auto & outputRegister = *node.
output(0);
1186 Set_->MapRegisterToExistingPointerObject(outputRegister, baseRegisterPO);
1194 const auto operation = util::assertedCast<const IOBarrierOperation>(&node.
GetOperation());
1198 const auto & inputRegister = *node.
input(0)->
origin();
1199 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1200 const auto & outputRegister = *node.
output(0);
1201 Set_->MapRegisterToExistingPointerObject(outputRegister, inputRegisterPO);
1240 auto & inputRegister = *cv.input->origin();
1241 auto & argumentRegister = *cv.inner;
1242 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1243 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1250 (
void)
Set_->CreateRegisterPointerObject(*argument);
1256 const auto lambdaPO =
Set_->CreateFunctionMemoryObject(lambda);
1259 const auto & lambdaOutput = *lambda.
output();
1260 const auto lambdaOutputPO =
Set_->CreateRegisterPointerObject(lambdaOutput);
1261 Constraints_->AddPointerPointeeConstraint(lambdaOutputPO, lambdaPO);
1273 auto & inputRegister = *cv.input->origin();
1274 auto & argumentRegister = *cv.inner;
1275 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1276 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1288 const auto globalPO =
Set_->CreateGlobalMemoryObject(delta, canPoint);
1293 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1298 auto & outputRegister = delta.
output();
1299 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(outputRegister);
1300 Constraints_->AddPointerPointeeConstraint(outputRegisterPO, globalPO);
1312 auto & inputRegister = *var.input->origin();
1313 auto & argumentRegister = *var.inner;
1314 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1315 Set_->MapRegisterToExistingPointerObject(argumentRegister, inputRegisterPO);
1324 auto & argumentRegister = *var.recref;
1325 (void)
Set_->CreateRegisterPointerObject(argumentRegister);
1337 auto & argumentRegister = *var.recref;
1338 auto & resultRegister = *var.result->origin();
1339 const auto argumentRegisterPO =
Set_->GetRegisterPointerObject(argumentRegister);
1340 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(resultRegister);
1344 auto & outputRegister = *var.output;
1345 Set_->MapRegisterToExistingPointerObject(outputRegister, resultRegisterPO);
1358 auto & inputRegister = *ev.input->origin();
1359 const auto inputRegisterPO =
Set_->GetRegisterPointerObject(inputRegister);
1361 for (
auto & argument : ev.branchArgument)
1362 Set_->MapRegisterToExistingPointerObject(*argument, inputRegisterPO);
1375 auto & outputRegister = ex.output;
1376 const auto outputRegisterPO =
Set_->CreateRegisterPointerObject(*outputRegister);
1378 for (
auto result : ex.branchResult)
1380 const auto resultRegisterPO =
Set_->GetRegisterPointerObject(*result->origin());
1396 auto & inputReg = *loopVar.input->origin();
1397 auto & innerArgumentReg = *loopVar.pre;
1398 const auto inputRegPO =
Set_->GetRegisterPointerObject(inputReg);
1399 const auto innerArgumentRegPO =
Set_->CreateRegisterPointerObject(innerArgumentReg);
1414 auto & innerArgumentReg = *loopVar.pre;
1415 auto & innerResultReg = *loopVar.post->origin();
1416 auto & outputReg = *loopVar.output;
1418 const auto innerArgumentRegPO =
Set_->GetRegisterPointerObject(innerArgumentReg);
1419 const auto innerResultRegPO =
Set_->GetRegisterPointerObject(innerResultReg);
1425 Set_->MapRegisterToExistingPointerObject(outputReg, innerResultRegPO);
1433 for (
size_t i = 0; i < region.
narguments(); i++)
1445 for (
const auto node : traverser)
1455 for (
size_t i = 0; i < node->noutputs(); i++)
1470 for (
size_t n = 0; n < rootRegion.narguments(); n++)
1472 auto & argument = *util::assertedCast<LlvmGraphImport>(rootRegion.argument(n));
1484 const auto importObjectPO =
Set_->CreateImportMemoryObject(argument, canPoint);
1487 const auto importRegisterPO =
Set_->CreateRegisterPointerObject(argument);
1488 Constraints_->AddPointerPointeeConstraint(importRegisterPO, importObjectPO);
1494 for (
size_t n = 0; n < rootRegion.nresults(); n++)
1496 auto & escapedRegister = *rootRegion.result(n)->origin();
1500 const auto escapedRegisterPO =
Set_->GetRegisterPointerObject(escapedRegister);
1501 Constraints_->AddRegisterContentEscapedConstraint(escapedRegisterPO);
1520 Set_ = std::make_unique<PointerObjectSet>();
1574std::unique_ptr<PointsToGraph>
1580 statistics->StartAndersenStatistics(module.
Rvsdg());
1583 size_t testAllConfigsIterations = 0;
1585 testAllConfigsIterations = std::stoi(testAllConfigsString);
1586 std::optional<size_t> useExactConfig;
1588 useExactConfig = std::stoi(useExactConfigString);
1597 std::pair<std::unique_ptr<PointerObjectSet>, std::unique_ptr<PointerObjectConstraintSet>> copy;
1598 if (testAllConfigsIterations || doubleCheck)
1606 if (useExactConfig.has_value())
1609 config = allConfigs.at(*useExactConfig);
1613 statistics->AddStatisticsFromSolution(*
Set_);
1618 graph.AppendToLabel(
"After Solving with " + config.ToString());
1624 statistics->StopAndersenStatistics();
1628 if (testAllConfigsIterations || doubleCheck)
1631 std::cerr <<
"Double checking Andersen analysis using naive solving" << std::endl;
1634 std::vector<Configuration> configs;
1635 if (testAllConfigsIterations)
1642 const auto iterations = std::max<size_t>(testAllConfigsIterations, 1);
1644 for (
size_t i = 0; i < iterations; i++)
1646 for (
const auto & config : configs)
1649 auto workingCopy = copy.second->Clone();
1653 solvingStats->AddStatisticsFromSolution(*workingCopy.first);
1657 if (doubleCheck && i == 0)
1659 if (workingCopy.first->HasIdenticalSolAs(*
Set_))
1662 <<
" did not produce the same solution as the config " << config.ToString()
1664 JLM_UNREACHABLE(
"Andersen solver double checking uncovered differences!");
1676std::unique_ptr<PointsToGraph>
1683std::unique_ptr<PointsToGraph>
1693 std::unordered_map<PointerObjectIndex, PointsToGraph::NodeIndex> memoryNodeMapping;
1695 for (
auto [allocaNode, pointerObjectIndex] : set.
GetAllocaMap())
1697 memoryNodeMapping[pointerObjectIndex] =
1698 pointsToGraph->addNodeForAlloca(*allocaNode, set.
HasEscaped(pointerObjectIndex));
1701 for (
auto [deltaNode, pointerObjectIndex] : set.
GetGlobalMap())
1703 memoryNodeMapping[pointerObjectIndex] =
1704 pointsToGraph->addNodeForDelta(*deltaNode, set.
HasEscaped(pointerObjectIndex));
1707 for (
auto [
import, pointerObjectIndex] : set.
GetImportMap())
1709 memoryNodeMapping[pointerObjectIndex] =
1710 pointsToGraph->addNodeForImport(*
import, set.
HasEscaped(pointerObjectIndex));
1713 for (
auto [lambdaNode, pointerObjectIndex] : set.
GetFunctionMap())
1715 memoryNodeMapping[pointerObjectIndex] =
1716 pointsToGraph->addNodeForLambda(*lambdaNode, set.
HasEscaped(pointerObjectIndex));
1719 for (
auto [mallocNode, pointerObjectIndex] : set.
GetMallocMap())
1721 memoryNodeMapping[pointerObjectIndex] =
1722 pointsToGraph->addNodeForMalloc(*mallocNode, set.
HasEscaped(pointerObjectIndex));
1739 pointsToGraph->markAsTargetsAllExternallyAvailable(ptgNode);
1745 pointsToGraph->addTarget(ptgNode, memoryNodeMapping[targetIdx]);
1752 std::unordered_map<PointerObjectIndex, util::HashSet<const rvsdg::Output *>> outputsInRegister;
1756 outputsInRegister[root].insert(outputNode);
1760 for (
auto & [registerIdx, outputNodes] : outputsInRegister)
1762 const auto ptgNode = pointsToGraph->addNodeForRegisters();
1763 for (
auto outputNode : outputNodes.Items())
1764 pointsToGraph->mapRegisterToNode(*outputNode, ptgNode);
1765 applyPointsToSet(ptgNode, registerIdx);
1769 for (
auto [pointerObjectSetIndex, ptgNode] : memoryNodeMapping)
1771 applyPointsToSet(ptgNode, pointerObjectSetIndex);
1775 return pointsToGraph;
1778std::unique_ptr<PointsToGraph>
static jlm::util::StatisticsCollector statisticsCollector
static rvsdg::Input & GetFunctionInput(const rvsdg::Node &node) noexcept
ConstantPointerNullOperation class.
Get address of compiled function object.
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & addressOutput(const rvsdg::Node &node)
static rvsdg::Input & destinationInput(const rvsdg::Node &node) noexcept
Interpret pointer as callable function.
PoisonValueOperation class.
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
UndefValueOperation class.
bool EnableOfflineConstraintNormalization_
bool EnableHybridCycleDetection_
bool IsOfflineVariableSubstitutionEnabled() const noexcept
bool IsLazyCycleDetectionEnabled() const noexcept
bool EnableOnlineCycleDetection_
PointerObjectConstraintSet::WorklistSolverPolicy GetWorklistSoliverPolicy() const noexcept
std::string ToString() const
bool EnableDifferencePropagation_
bool IsHybridCycleDetectionEnabled() const noexcept
bool IsPreferImplicitPointeesEnabled() const noexcept
bool IsDifferencePropagationEnabled() const noexcept
static Configuration NaiveSolverConfiguration() noexcept
PointerObjectConstraintSet::WorklistSolverPolicy WorklistSolverPolicy_
bool IsOnlineCycleDetectionEnabled() const noexcept
static std::vector< Configuration > GetAllConfigurations()
bool EnablePreferImplicitPointees_
bool EnableLazyCycleDetection_
bool IsOfflineConstraintNormalizationEnabled() const noexcept
Solver GetSolver() const noexcept
bool EnableOfflineVariableSubstitution_
void StartPointsToGraphConstructionStatistics()
void StartConstraintSolvingNaiveStatistics() noexcept
Statistics(const util::FilePath &sourceFile)
void StopAndersenStatistics() noexcept
void StartSetAndConstraintBuildingStatistics() noexcept
void StartConstraintSolvingWorklistStatistics() noexcept
void StartOfflineConstraintNormalization() noexcept
void StopOfflineVariableSubstitution(size_t numUnifications) noexcept
~Statistics() override=default
void StartOfflineVariableSubstitution() noexcept
void AddStatisticsFromSolution(const PointerObjectSet &set)
void StopPointsToGraphConstructionStatistics(const PointsToGraph &pointsToGraph)
void StopSetAndConstraintBuildingStatistics(const PointerObjectSet &set, const PointerObjectConstraintSet &constraints) noexcept
void StopOfflineConstraintNormalization(size_t numConstraintsRemoved) noexcept
void StartAndersenStatistics(const rvsdg::Graph &graph) noexcept
void StopConstraintSolvingNaiveStatistics(size_t numIterations) noexcept
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile)
void AddStatisticFromConfiguration(const Configuration &config)
void StopExternalToAllEscapedStatistics()
void StartExternalToAllEscapedStatistics()
void StopConstraintSolvingWorklistStatistics(PointerObjectConstraintSet::WorklistStatistics &statistics) noexcept
void AnalyzeIOBarrier(const rvsdg::SimpleNode &node)
const Configuration & GetConfiguration() const
void AnalyzeMemmove(const rvsdg::SimpleNode &node)
static void SolveConstraints(PointerObjectConstraintSet &constraints, const Configuration &config, Statistics &statistics)
void AnalyzePoison(const rvsdg::SimpleNode &node)
void AnalyzeConstantPointerNull(const rvsdg::SimpleNode &node)
void SetConfiguration(Configuration config)
void AnalyzePtrMask(const rvsdg::SimpleNode &node)
void AnalyzeValist(const rvsdg::SimpleNode &node)
void AnalyzePointerToFunction(const rvsdg::SimpleNode &node)
void AnalyzeStore(const rvsdg::SimpleNode &node)
static const char *const ENV_USE_EXACT_CONFIG
std::unique_ptr< PointerObjectSet > Set_
void AnalyzeUndef(const rvsdg::SimpleNode &node)
static std::unique_ptr< PointsToGraph > ConstructPointsToGraphFromPointerObjectSet(const PointerObjectSet &set, Statistics &statistics)
static const char *const ENV_DOUBLE_CHECK
void AnalyzeRegion(rvsdg::Region ®ion)
void AnalyzeGep(const rvsdg::SimpleNode &node)
~Andersen() noexcept override
void AnalyzeRvsdg(const rvsdg::Graph &graph)
void AnalyzeAlloca(const rvsdg::SimpleNode &node)
void AnalyzeModule(const rvsdg::RvsdgModule &module, Statistics &statistics)
void AnalyzePtrToInt(const rvsdg::SimpleNode &node)
void AnalyzeMemset(const rvsdg::SimpleNode &node)
std::unique_ptr< PointsToGraph > Analyze(const rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
void AnalyzeExtractValue(const rvsdg::SimpleNode &node)
void AnalyzeConstantArray(const rvsdg::SimpleNode &node)
void AnalyzeInsertValue(const rvsdg::SimpleNode &node)
void AnalyzeConstantAggregateZero(const rvsdg::SimpleNode &node)
void AnalyzeBitcast(const rvsdg::SimpleNode &node)
void AnalyzePhi(const rvsdg::PhiNode &node)
static const char *const ENV_DUMP_SUBSET_GRAPH
void AnalyzeMemcpy(const rvsdg::SimpleNode &node)
void AnalyzeCall(const rvsdg::SimpleNode &callNode)
void AnalyzeConstantStruct(const rvsdg::SimpleNode &node)
std::unique_ptr< PointerObjectConstraintSet > Constraints_
void AnalyzeTheta(const rvsdg::ThetaNode &node)
void AnalyzeFreeze(const rvsdg::SimpleNode &node)
void AnalyzeMalloc(const rvsdg::SimpleNode &node)
void AnalyzeLambda(const rvsdg::LambdaNode &node)
void AnalyzeBits2ptr(const rvsdg::SimpleNode &node)
void AnalyzeLoad(const rvsdg::SimpleNode &node)
void AnalyzeSimpleNode(const rvsdg::SimpleNode &node)
void AnalyzeFunctionToPointer(const rvsdg::SimpleNode &node)
void AnalyzeGamma(const rvsdg::GammaNode &node)
void AnalyzeStructuralNode(const rvsdg::StructuralNode &node)
static const char *const ENV_TEST_ALL_CONFIGS
void AnalyzeDelta(const rvsdg::DeltaNode &node)
size_t NormalizeConstraints()
size_t PerformOfflineVariableSubstitution(bool storeRefCycleUnificationRoot)
WorklistStatistics SolveUsingWorklist(WorklistSolverPolicy policy, bool enableOnlineCycleDetection, bool enableHybridCycleDetection, bool enableLazyCycleDetection, bool enableDifferencePropagation, bool enablePreferImplicitPropation)
static const char * WorklistSolverPolicyToString(WorklistSolverPolicy policy)
const util::BijectiveMap< const rvsdg::LambdaNode *, PointerObjectIndex > & GetFunctionMap() const noexcept
size_t GetNumSetInsertionAttempts() const noexcept
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetMallocMap() const noexcept
size_t GetNumExplicitPointeesRemoved() const noexcept
const util::HashSet< PointerObjectIndex > & GetPointsToSet(PointerObjectIndex index) const
bool HasPointeesEscaping(PointerObjectIndex index) const noexcept
bool CanPoint(PointerObjectIndex index) const noexcept
const std::unordered_map< const rvsdg::SimpleNode *, PointerObjectIndex > & GetAllocaMap() const noexcept
bool IsPointingToExternal(PointerObjectIndex index) const noexcept
bool HasEscaped(PointerObjectIndex index) const noexcept
const std::unordered_map< const LlvmGraphImport *, PointerObjectIndex > & GetImportMap() const noexcept
const std::unordered_map< const rvsdg::DeltaNode *, PointerObjectIndex > & GetGlobalMap() const noexcept
PointerObjectIndex GetUnificationRoot(PointerObjectIndex index) const noexcept
bool IsUnificationRoot(PointerObjectIndex index) const noexcept
size_t NumPointerObjects() const noexcept
const std::unordered_map< const rvsdg::Output *, PointerObjectIndex > & GetRegisterMap() const noexcept
size_t numLambdaNodes() const noexcept
size_t numNodesTargetingAllExternallyAvailable() const noexcept
size_t numNodes() const noexcept
size_t numMemoryNodes() const noexcept
size_t numRegisterNodes() const noexcept
size_t numMallocNodes() const noexcept
size_t numExternallyAvailableNodes() const noexcept
size_t numDeltaNodes() const noexcept
static std::unique_ptr< PointsToGraph > create()
size_t numAllocaNodes() const noexcept
size_t numImportNodes() const noexcept
std::pair< size_t, size_t > numEdges() const noexcept
rvsdg::Input & result() const noexcept
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
rvsdg::Region * subregion() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
rvsdg::Output & output() const noexcept
Conditional operator / pattern matching.
std::vector< ExitVar > GetExitVars() const
Gets all exit variables for this gamma.
std::vector< EntryVar > GetEntryVars() const
Gets all entry variables for this gamma.
Region & GetRootRegion() const noexcept
std::vector< rvsdg::Output * > GetFunctionArguments() const
rvsdg::Output * output() const noexcept
rvsdg::Region * subregion() const noexcept
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
size_t ninputs() const noexcept
size_t noutputs() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
A phi node represents the fixpoint of mutually recursive definitions.
std::vector< FixVar > GetFixVars() const noexcept
Gets all fixpoint variables.
std::vector< ContextVar > GetContextVars() const noexcept
Gets all bound context variables.
rvsdg::Region * subregion() const noexcept
Represent acyclic RVSDG subgraphs.
RegionArgument * argument(size_t index) const noexcept
size_t narguments() const noexcept
const std::optional< util::FilePath > & SourceFilePath() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
NodeOutput * output(size_t index) const noexcept
rvsdg::Region * subregion(size_t index) const noexcept
size_t nsubregions() const noexcept
std::vector< LoopVar > GetLoopVars() const
Returns all loop variables.
rvsdg::Region * subregion() const noexcept
std::size_t Size() const noexcept
IteratorRange< ItemConstIterator > Items() const noexcept
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
void outputAllGraphs(std::ostream &out, OutputFormat format)
#define JLM_UNREACHABLE(msg)
bool IsOrContainsPointerType(const rvsdg::Type &type)
uint32_t PointerObjectIndex
bool IsAggregateType(const jlm::rvsdg::Type &type)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.